Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

วิธีการเขียน Port Scanner ใน Ruby

ทำไมคุณถึงต้องการเขียนเครื่องสแกนพอร์ต

การเขียน 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 ใหม่เริ่มต้นอย่างไร

วิธีการเขียน Port Scanner ใน Ruby

การเชื่อมต่อ TCP ใหม่เริ่มต้นด้วย SYN แพ็คเก็ต แพ็กเก็ตนี้เป็นสัญลักษณ์ของการเริ่มต้นการเชื่อมต่อใหม่

มีผลลัพธ์ที่เป็นไปได้สามประการ :

  • เซิร์ฟเวอร์ตอบด้วย SYN/ACK – หมายความว่าพร้อมที่จะสร้างการเชื่อมต่อ
  • เซิร์ฟเวอร์ตอบด้วย RST แพ็กเก็ต – หมายความว่าการเชื่อมต่อถูกปฏิเสธ
  • เซิร์ฟเวอร์ไม่ตอบเลย (ไฟร์วอลล์บางตัวใช้สิ่งนี้เป็นนโยบาย DROP)

หากลูกค้าได้รับ SYN/ACK แพ็กเก็ตก็สามารถสร้างการเชื่อมต่อให้เสร็จได้โดยส่ง ACK แพ็กเก็ต

สิ่งนี้เรียกว่า “การจับมือสามทาง “.

หมายเหตุ :วิธีที่ยอดเยี่ยมในการรับชมสิ่งนี้คือการใช้เครื่องมือเครือข่าย เช่น tcpdump หรือ wireshark เครื่องมือเหล่านี้ช่วยให้คุณเห็นทุกแพ็กเก็ตที่เข้าและออกจากระบบของคุณ

นี่คือตัวอย่างการเชื่อมต่อจาก tshark (อินเทอร์เฟซบรรทัดคำสั่งของ wireshark):

วิธีการเขียน Port Scanner ใน Ruby

เมื่อคุณมีความเข้าใจพื้นฐานเกี่ยวกับวิธีสร้างการเชื่อมต่อ 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:

วิธีการเขียน Port Scanner ใน Ruby

ฉันรู้ว่านั่นเป็นข้อมูลจำนวนมาก ดังนั้นเพื่อช่วยให้คุณจำได้ว่าเขียนความคิดเห็นพร้อม 2 สิ่งใหม่ที่คุณได้เรียนรู้จากโพสต์นี้ 🙂

สรุป

ในโพสต์นี้ คุณได้เรียนรู้ว่าพอร์ตคืออะไร ช่วงพอร์ตต่างๆ ที่พร้อมใช้งาน วิธีเริ่มต้นการเชื่อมต่อ TCP (การจับมือสามทาง) และวิธีเขียนเครื่องสแกนพอร์ตพื้นฐานโดยใช้ Ruby

หากคุณชอบโพสต์นี้ อย่าลืมแชร์ให้คนอื่นได้สนุกด้วย 🙂