ทำไมคุณถึงต้องการเขียนเครื่องสแกนพอร์ต
การเขียน port scanner เป็นวิธีที่ยอดเยี่ยมในการเรียนรู้พื้นฐานของโปรโตคอล TCP ซึ่งเป็น transport layer ใช้โดยโปรโตคอลอินเทอร์เน็ตส่วนใหญ่ (รวมถึง HTTP &SSH)
นอกจากนี้ยังเป็นแบบฝึกหัดที่ดีที่จะเรียนรู้เพิ่มเติมเกี่ยวกับวิธีการทำงานของการเขียนโปรแกรมเครือข่าย Ruby
มาเริ่มด้วยการพูดถึงพอร์ตกันเถอะ!
ท่าเรือคืออะไร
เมื่อเราพูดถึงพอร์ต เรากำลังพูดถึงอะไรกันแน่? ท่าเรือที่ O.S. (ระบบปฏิบัติการ) เป็นเพียง "ตัวอธิบายไฟล์" ที่เกี่ยวข้องกับกระบวนการ
ตัวอธิบายไฟล์ เป็นเพียงตัวเลขที่ใช้อ้างอิงช่อง I/O ที่เปิดอยู่ เช่น stdout
(เอาต์พุตมาตรฐาน) ซ็อกเก็ตเครือข่ายหรือไฟล์
เมื่อระบบปฏิบัติการได้รับแพ็กเก็ต TCP/IP จะดูที่พอร์ตปลายทาง &พยายามค้นหากระบวนการที่กำลังฟังอยู่บนพอร์ตนี้
จากนั้นหากมีกระบวนการรับฟัง แพ็กเก็ตก็จะถูกส่งไป
ช่วงพอร์ต
มีพอร์ตทั้งหมด 65.535 พอร์ต แต่ในทางปฏิบัติไม่ได้ใช้งานทุกพอร์ตเป็นประจำ
พอร์ตสามารถแบ่งออกเป็น 3 กลุ่ม:
ช่วง | ชื่อ | ตัวอย่าง |
---|---|---|
1-1023 | พอร์ตที่รู้จักกันดี | 22 (SSH), 80 (HTTP), 443 (HTTPS) |
1024-49151 | พอร์ตที่ลงทะเบียน | 3306 (MySQL), 5432 (PostgreSQL) |
49152-65535 | พอร์ตชั่วคราว | Chrome, Firefox |
พอร์ตในช่วงที่ 2 ถูกกำหนดโดย IANA (Internet Assigned Numbers Authority)
และช่วงที่ 3 ใช้สำหรับพอร์ต "ไดนามิก" หรือ "ชั่วคราว" ซึ่งเป็นพอร์ตที่ฝั่งไคลเอ็นต์ของการเชื่อมต่อใช้เพื่อรับข้อมูลจากเซิร์ฟเวอร์
พื้นฐานของการสื่อสาร TCP
ตอนนี้คุณควรจะคุ้นเคยกับพอร์ตมากขึ้น แต่เรายังไม่พร้อมที่จะเขียนเครื่องสแกนพอร์ตของเรา
อันดับแรก เราต้องคุยกันก่อนว่าการเปิดพอร์ตหมายความว่าอย่างไร จากนั้นเราจะตรวจสอบพฤติกรรมของทั้งพอร์ตเปิดและพอร์ตปิดที่ระดับเครือข่ายเพื่อแยกความแตกต่าง
คุณจะทราบได้อย่างไรว่าพอร์ตเปิดอยู่
พอร์ตเปิดหมายความว่ามีแอปพลิเคชันที่รับฟังอยู่อีกด้านหนึ่ง &ที่เราสามารถเข้าถึงได้ (ไม่ถูกบล็อกโดยไฟร์วอลล์)
มาดูกันว่าการเชื่อมต่อ TCP ใหม่เริ่มต้นอย่างไร
การเชื่อมต่อ TCP ใหม่เริ่มต้นด้วย SYN
แพ็คเก็ต แพ็กเก็ตนี้เป็นสัญลักษณ์ของการเริ่มต้นการเชื่อมต่อใหม่
มีผลลัพธ์ที่เป็นไปได้สามประการ :
- เซิร์ฟเวอร์ตอบด้วย
SYN/ACK
– หมายความว่าพร้อมที่จะสร้างการเชื่อมต่อ - เซิร์ฟเวอร์ตอบด้วย
RST
แพ็กเก็ต – หมายความว่าการเชื่อมต่อถูกปฏิเสธ - เซิร์ฟเวอร์ไม่ตอบเลย (ไฟร์วอลล์บางตัวใช้สิ่งนี้เป็นนโยบาย DROP)
หากลูกค้าได้รับ SYN/ACK
แพ็กเก็ตก็สามารถสร้างการเชื่อมต่อให้เสร็จได้โดยส่ง ACK
แพ็กเก็ต
สิ่งนี้เรียกว่า “การจับมือสามทาง “.
หมายเหตุ :วิธีที่ยอดเยี่ยมในการรับชมสิ่งนี้คือการใช้เครื่องมือเครือข่าย เช่น tcpdump หรือ wireshark เครื่องมือเหล่านี้ช่วยให้คุณเห็นทุกแพ็กเก็ตที่เข้าและออกจากระบบของคุณ
นี่คือตัวอย่างการเชื่อมต่อจาก tshark (อินเทอร์เฟซบรรทัดคำสั่งของ wireshark):
เมื่อคุณมีความเข้าใจพื้นฐานเกี่ยวกับวิธีสร้างการเชื่อมต่อ TCP แล้ว เราก็สามารถเขียนเครื่องสแกนพอร์ตอย่างง่ายได้
มาเขียน Port Scanner กันเถอะ!
วิธีที่ง่ายที่สุดในการเขียนสแกนเนอร์ของเราคือเปิดการเชื่อมต่อ TCP ใหม่โดยใช้ TCPSocket
&จากนั้นอาศัยความจริงที่ว่าการเชื่อมต่อที่ถูกปฏิเสธจะเพิ่ม Errno::ECONNREFUSED
ข้อยกเว้น
นี่คือรหัส :
require 'socket'PORT =ARGV[0] || 22HOST =ARGV [1] || 'localhost'begin socket =TCPSocket.new(HOST, PORT) status ="open"rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT status ="closed"endputs "Port #{PORT} is #{status}." ก่อน>รหัสนี้มีข้อจำกัดบางประการ:
เราสามารถสแกนได้ครั้งละหนึ่งพอร์ตเท่านั้น บ่อยครั้งคุณต้องการสแกนพอร์ตต่างๆ เพื่อให้ได้แนวคิดที่ดีขึ้นว่าบริการใดบ้างที่เปิดเผยบนโฮสต์เฉพาะ
ข้อจำกัดอีกประการของรหัสนี้คือพอร์ตที่ไม่ตอบสนอง (ผลลัพธ์ที่สามที่ฉันกล่าวถึงก่อนหน้านี้) จะทำให้คุณรอประมาณ 20 วินาทีจนกว่าการเชื่อมต่อจะหมดเวลา
ซึ่งสามารถแก้ไขได้ด้วย
connect_nonblock
,IO.select
&Socket
(แทนTCPSocket
ซึ่งเริ่มต้นการเชื่อมต่อทันทีที่คุณสร้างวัตถุ)ตัวอย่าง :
ต้องการ 'socket'TIMEOUT =2def scan_port(port) socket =Socket.new(:INET, :STREAM) remote_addr =Socket.sockaddr_in(port, 'www.example.com') เริ่มช่วยเหลือ socket.connect_nonblock(remote_addr) Errno::EINPROGRESS end _, sockets, _ =IO.select(nil, [socket], nil, TIMEOUT) ถ้า sockets p "Port #{port} is open" else # Port is closed endendPORT_LIST =[21,22,23 ,25,53,80,443,3306,8080]กระทู้ =[]PORT_LIST.each { |i| กระทู้ <
IO.select
การโทรจะรอจนกว่าซ็อกเก็ตจะพร้อมรับข้อมูล (ซึ่งหมายความว่าเปิดอยู่) หรือจนกว่าTIMEOUT
เวลาผ่านไปหลังจากนั้นเราสามารถสรุปได้ว่าพอร์ตปิดหรือเพิกเฉยต่อคำขอเชื่อมต่อทั้งหมดนี้ถือเป็นแบบฝึกหัดการเรียนรู้ที่ดี แต่ถ้าคุณต้องการเครื่องสแกนพอร์ตที่เหมาะสม คุณควรใช้บางอย่างเช่น nmap
Nmap เป็นโอเพ่นซอร์สและอยู่ภายใต้การพัฒนามานานกว่า 15 ปี
นี่คือลักษณะของเอาต์พุต nmap:
ฉันรู้ว่านั่นเป็นข้อมูลจำนวนมาก ดังนั้นเพื่อช่วยให้คุณจำได้ว่าเขียนความคิดเห็นพร้อม 2 สิ่งใหม่ที่คุณได้เรียนรู้จากโพสต์นี้ 🙂
สรุป
ในโพสต์นี้ คุณได้เรียนรู้ว่าพอร์ตคืออะไร ช่วงพอร์ตต่างๆ ที่พร้อมใช้งาน วิธีเริ่มต้นการเชื่อมต่อ TCP (การจับมือสามทาง) และวิธีเขียนเครื่องสแกนพอร์ตพื้นฐานโดยใช้ Ruby
หากคุณชอบโพสต์นี้ อย่าลืมแชร์ให้คนอื่นได้สนุกด้วย 🙂