Computer >> 컴퓨터 >  >> 프로그램 작성 >> Ruby

Ruby에서 포트 스캐너를 작성하는 방법

왜 포트 스캐너를 만들고 싶습니까?

포트 스캐너를 작성하는 것은 전송 계층인 TCP 프로토콜의 기초를 배울 수 있는 좋은 방법입니다. 대부분의 인터넷 프로토콜(HTTP 및 SSH 포함)에서 사용됩니다.

Ruby 네트워크 프로그래밍 작동 방식에 대해 자세히 알아보는 것도 좋은 연습입니다.

포트에 대해 이야기하면서 시작하겠습니다!

포트란 무엇입니까?

우리가 포트에 대해 이야기할 때 우리가 실제로 말하는 것은 무엇입니까? O.S.의 항구 (운영 체제) 수준은 프로세스와 관련된 "파일 설명자"일 뿐입니다.

파일 설명자 stdout과 같이 열린 I/O 채널을 참조하는 데 사용되는 숫자일 뿐입니다. (표준 출력), 네트워크 소켓 또는 파일.

OS가 TCP/IP 패킷을 수신하면 대상 포트를 보고 이 포트에서 수신 대기 중인 프로세스를 찾으려고 합니다.

그런 다음 수신 프로세스가 있으면 패킷이 전달됩니다.

포트 범위

총 65.535개의 포트를 사용할 수 있지만 실제로 모든 포트가 정기적으로 사용되는 것은 아닙니다.

포트는 3개의 그룹으로 나눌 수 있습니다.

범위 이름
1-1023 잘 알려진 포트 22(SSH), 80(HTTP), 443(HTTPS)
1024-49151 등록된 포트 3306(MySQL), 5432(PostgreSQL)
49152-65535 임시 포트 크롬, 파이어폭스

두 번째 범위의 포트는 IANA(Internet Assigned Numbers Authority)에서 할당합니다.

그리고 세 번째 범위는 "동적" 또는 "임시" 포트에 사용되며, 이는 서버에서 데이터를 수신하기 위해 연결의 클라이언트 측에서 사용하는 포트입니다.

TCP 통신의 기본

이제 포트에 더 익숙해져야 하지만 아직 포트 스캐너를 작성할 준비가 되지 않았습니다.

먼저 포트가 열려 있다는 것이 무엇을 의미하는지 논의해야 합니다. 그런 다음 네트워크 수준에서 개방형 포트와 폐쇄형 포트의 동작을 검사하여 구분할 수 있습니다.

포트가 열려 있는지 어떻게 알 수 있나요?

열린 포트는 다른 쪽 끝에서 수신 대기 중인 애플리케이션이 있고 우리가 이에 액세스할 수 있음을 의미합니다(방화벽에 의해 차단되지 않음).

새로운 TCP 연결이 어떻게 시작되는지 봅시다.

Ruby에서 포트 스캐너를 작성하는 방법

새 TCP 연결은 SYN으로 시작됩니다. 패킷. 이 패킷은 새로운 연결의 시작을 상징합니다.

세 가지 가능한 결과가 있습니다. :

  • 서버는 SYN/ACK로 응답합니다. – 이것은 연결을 설정할 준비가 되었음을 의미합니다.
  • 서버는 RST로 응답합니다. 패킷 – 연결이 거부되었음을 의미합니다.
  • 서버가 전혀 응답하지 않음(일부 방화벽은 이를 DROP 정책으로 구현)

클라이언트가 SYN/ACK를 수신하는 경우 패킷을 보낸 후 ACK를 전송하여 연결 설정을 완료할 수 있습니다. 패킷.

이를 '3방향 핸드셰이크라고 합니다. ".

<블록 인용>

참고 :이런 일이 일어나는 것을 보는 좋은 방법은 tcpdump나 wireshark와 같은 네트워킹 도구를 사용하는 것입니다. 이 도구를 사용하면 시스템에서 들어오고 나가는 모든 패킷을 볼 수 있습니다.

다음은 shark의 연결 예입니다. (wireshark의 명령줄 인터페이스):

Ruby에서 포트 스캐너를 작성하는 방법

이제 TCP 연결이 설정되는 방법에 대한 기본적인 이해가 있으므로 간단한 포트 스캐너를 작성할 수 있습니다.

포트 스캐너를 작성해 봅시다!

스캐너를 작성하는 가장 간단한 방법은 TCPSocket을 사용하여 새 TCP 연결을 여는 것입니다. 그리고 거부된 연결이 Errno::ECONNREFUSED를 발생시킨다는 사실에 의존합니다. 예외.

코드는 다음과 같습니다. :

'소켓'PORT =ARGV[0] 필요 || 22호스트 =ARGV[1] || 'localhost'begin socket =TCPSocket.new(HOST, PORT) status ="open"rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT status ="closed" endputs "Port #{PORT}는 #{status}입니다." 

이 코드에는 몇 가지 제한 사항이 있습니다.

한 번에 하나의 포트만 스캔할 수 있습니다. 특정 호스트에서 어떤 서비스가 노출되는지 더 잘 파악하기 위해 다양한 포트를 스캔해야 하는 경우가 많습니다.

이 코드의 또 다른 한계는 응답하지 않는 포트(앞서 언급한 결과의 세 번째)로 인해 연결 시간이 초과될 때까지 약 20초를 기다려야 한다는 것입니다.

connect_nonblock 조합으로 해결할 수 있습니다. , IO.select &Socket (대신 TCPSocket , 개체를 생성하는 즉시 연결을 시작합니다.

:

'소켓'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) if sockets p "Port #{port} is open" else # 포트가 닫혀 있음 endendPORT_LIST =[21,22,23 ,25,53,80,443,3306,8080]스레드 =[]PORT_LIST.각 { |i| 스레드 < 

IO.select 호출은 소켓이 데이터를 수신할 준비가 될 때까지(즉, 열려 있음을 의미함) 또는 TIMEOUT까지 기다립니다. 시간이 지나면 포트가 닫혀 있거나 연결 요청을 무시한다고 가정할 수 있습니다.

따라서 이것은 모두 학습 연습으로 훌륭하지만 적절한 포트 스캐너가 필요한 경우 nmap과 같은 것을 사용해야 합니다.

Nmap은 오픈 소스이며 15년 이상 동안 활발하게 개발되었습니다.

nmap 출력은 다음과 같습니다.

Ruby에서 포트 스캐너를 작성하는 방법

많은 정보라는 것을 알고 있으므로 이 게시물에서 배운 2가지 새로운 사실을 기억하는 데 도움이 되도록 댓글을 작성하세요 🙂

요약

이 게시물에서는 포트가 무엇인지, 사용 가능한 다양한 포트 범위, TCP 연결이 시작되는 방법(3방향 핸드셰이크) 및 Ruby를 사용하여 기본 포트 스캐너를 작성하는 방법을 배웠습니다.

이 게시물이 마음에 드셨다면 더 많은 사람들이 즐길 수 있도록 공유하는 것을 잊지 마세요 🙂