Python 네트워크 스캐너

포트 스캐닝은 특정 호스트에서 사용할 수있는 열린 포트를 찾는 데 사용되는 감시 기술로 정의 될 수 있습니다. 네트워크 관리자, 침투 테스터 또는 해커가이 기술을 사용할 수 있습니다. 대상 시스템에서 최대 정보를 얻기 위해 요구 사항에 따라 포트 스캐너를 구성 할 수 있습니다.

이제 포트 스캔을 실행 한 후 얻을 수있는 정보를 고려하십시오.

  • 열린 포트에 대한 정보.

  • 각 포트에서 실행되는 서비스에 대한 정보.

  • 대상 호스트의 OS 및 MAC 주소에 대한 정보입니다.

포트 스캔은 모든 문과 창문을 확인하여 어떤 것이 열려 있는지 확인하여 집에 들어 가려는 도둑과 같습니다. 앞서 논의했듯이 인터넷을 통한 통신에 사용되는 TCP / IP 프로토콜 제품군은 TCP와 UDP라는 두 가지 프로토콜로 구성됩니다. 두 프로토콜 모두 0 ~ 65535 포트가 있습니다. 따라서 기본적으로 시스템의 불필요한 포트를 닫는 것이 항상 권장되므로 잠글 수있는 도어 (포트)는 65000 개가 넘습니다. 이 65535 포트는 다음 세 가지 범위로 나눌 수 있습니다.

  • 시스템 또는 잘 알려진 포트 : 0 ~ 1023

  • 사용자 또는 등록 된 포트 : 1024 ~ 49151

  • 동적 또는 개인 포트 : 모두> 49151

소켓을 사용하는 포트 스캐너

이전 장에서 소켓이 무엇인지 논의했습니다. 이제 소켓을 사용하여 간단한 포트 스캐너를 만들 것입니다. 다음은 소켓을 사용하는 포트 스캐너 용 Python 스크립트입니다.

from socket import *
import time
startTime = time.time()

if __name__ == '__main__':
   target = input('Enter the host to be scanned: ')
   t_IP = gethostbyname(target)
   print ('Starting scan on host: ', t_IP)
   
   for i in range(50, 500):
      s = socket(AF_INET, SOCK_STREAM)
      
      conn = s.connect_ex((t_IP, i))
      if(conn == 0) :
         print ('Port %d: OPEN' % (i,))
      s.close()
print('Time taken:', time.time() - startTime)

위의 스크립트를 실행하면 호스트 이름을 입력하라는 메시지가 표시됩니다. 웹 사이트의 이름과 같은 호스트 이름을 제공 할 수 있지만 포트 스캔은 범죄로 보거나 해석 될 수 있으므로주의해야합니다. 당사는 귀하가 대상으로하는 서버 또는 컴퓨터 소유자의 명시적인 서면 허가없이 웹 사이트 또는 IP 주소에 대해 포트 스캐너를 실행해서는 안됩니다. 포트 스캔은 누군가의 집에 가서 문과 창문을 확인하는 것과 비슷합니다. 그렇기 때문에 localhost 또는 자신의 웹 사이트 (있는 경우)에서 포트 스캐너를 사용하는 것이 좋습니다.

산출

위의 스크립트는 다음 출력을 생성합니다.

Enter the host to be scanned: localhost
Starting scan on host: 127.0.0.1
Port 135: OPEN
Port 445: OPEN
Time taken: 452.3990001678467

출력은 50-500 범위 (스크립트에 제공된대로)에서이 포트 스캐너가 두 개의 포트 (포트 135 및 445가 열려 있음)를 발견했음을 보여줍니다. 이 범위를 변경하고 다른 포트를 확인할 수 있습니다.

ICMP를 사용하는 포트 스캐너 (네트워크의 라이브 호스트)

ICMP는 포트 스캔이 아니지만 호스트가 작동 중인지 확인하기 위해 원격 호스트를 ping하는 데 사용됩니다. 이 스캔은 네트워크에서 여러 라이브 호스트를 확인해야 할 때 유용합니다. 여기에는 ICMP ECHO 요청을 호스트에 보내는 것이 포함되며 해당 호스트가 활성 상태이면 ICMP ECHO 응답을 반환합니다.

위의 ICMP 요청 전송 프로세스를 ping 스캔이라고도하며 운영 체제의 ping 명령에 의해 제공됩니다.

Ping Sweep의 개념

실제로 하나 또는 다른 의미에서 핑 스위핑은 핑 스위핑이라고도합니다. 유일한 차이점은 핑 스위핑은 특정 네트워크 범위에서 둘 이상의 시스템 가용성을 찾는 절차라는 것입니다. 예를 들어, 전체 IP 주소 목록을 테스트하려는 경우 ping 스캔을 사용하여 즉, 운영 체제의 ping 명령을 사용하여 IP 주소를 하나씩 스캔하는 데 시간이 많이 걸립니다. 이것이 우리가 핑 스윕 스크립트를 사용해야하는 이유입니다. 다음은 핑 스윕을 사용하여 라이브 호스트를 찾는 Python 스크립트입니다.

import os
import platform

from datetime import datetime
net = input("Enter the Network Address: ")
net1= net.split('.')
a = '.'

net2 = net1[0] + a + net1[1] + a + net1[2] + a
st1 = int(input("Enter the Starting Number: "))
en1 = int(input("Enter the Last Number: "))
en1 = en1 + 1
oper = platform.system()

if (oper == "Windows"):
   ping1 = "ping -n 1 "
elif (oper == "Linux"):
   ping1 = "ping -c 1 "
else :
   ping1 = "ping -c 1 "
t1 = datetime.now()
print ("Scanning in Progress:")

for ip in range(st1,en1):
   addr = net2 + str(ip)
   comm = ping1 + addr
   response = os.popen(comm)
   
   for line in response.readlines():
      if(line.count("TTL")):
         break
      if (line.count("TTL")):
         print (addr, "--> Live")
         
t2 = datetime.now()
total = t2 - t1
print ("Scanning completed in: ",total)

위의 스크립트는 세 부분으로 작동합니다. 먼저 IP 주소를 여러 부분으로 분할하여 ping 스윕 스캔을 수행 할 IP 주소 범위를 선택합니다. 그 다음에는 운영 체제에 따라 핑 스위핑 명령을 선택하는 기능을 사용하고 마지막으로 호스트에 대한 응답과 검색 프로세스를 완료하는 데 걸린 시간을 제공합니다.

산출

위의 스크립트는 다음 출력을 생성합니다.

Enter the Network Address: 127.0.0.1
Enter the Starting Number: 1
Enter the Last Number: 100

Scanning in Progress:
Scanning completed in: 0:00:02.711155

위의 출력은 방화벽이 켜져 있고 ICMP 인바운드 설정도 비활성화되어 있기 때문에 라이브 포트가 없음을 보여줍니다. 이러한 설정을 변경 한 후 출력에 제공된 1 ~ 100 범위의 라이브 포트 목록을 가져올 수 있습니다.

TCP 스캔을 사용하는 포트 스캐너

TCP 연결을 설정하려면 호스트가 3 방향 핸드 셰이크를 수행해야합니다. 작업을 수행하려면 다음 단계를 따르십시오.

Step 1 − Packet with SYN flag set

이 단계에서 연결을 시작하려는 시스템은 SYN 플래그가 설정된 패킷으로 시작합니다.

Step 2 − Packet with SYN-ACK flag set

이 단계에서 대상 시스템은 SYN 및 ACK 플래그가 설정된 패킷을 반환합니다.

Step 3 − Packet with ACK flag set

마지막으로 시작 시스템은 ACK 플래그가 설정된 원래 대상 시스템으로 패킷을 반환합니다.

그럼에도 불구하고 여기서 제기되는 질문은 ICMP 에코 요청 및 응답 방법 (핑 스윕 스캐너)을 사용하여 포트 스캔을 수행 할 수 있는지 여부입니다. 그러면 왜 TCP 스캔이 필요합니까? 그 뒤에있는 주된 이유는 ICMP ECHO 응답 기능을 끄거나 방화벽을 ICMP 패킷에 사용하면 ping 스윕 스캐너가 작동하지 않고 TCP 스캔이 필요하기 때문입니다.

import socket
from datetime import datetime
net = input("Enter the IP address: ")
net1 = net.split('.')
a = '.'

net2 = net1[0] + a + net1[1] + a + net1[2] + a
st1 = int(input("Enter the Starting Number: "))
en1 = int(input("Enter the Last Number: "))
en1 = en1 + 1
t1 = datetime.now()

def scan(addr):
   s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
   socket.setdefaulttimeout(1)
   result = s.connect_ex((addr,135))
   if result == 0:
      return 1
   else :
      return 0

def run1():
   for ip in range(st1,en1):
      addr = net2 + str(ip)
      if (scan(addr)):
         print (addr , "is live")
         
run1()
t2 = datetime.now()
total = t2 - t1
print ("Scanning completed in: " , total)

위의 스크립트는 세 부분으로 작동합니다. 핑 스윕 스캔 할 IP 주소 범위를 여러 부분으로 분할하여 선택합니다. 그 다음에는 소켓을 더 사용하는 주소 스캔 기능을 사용합니다. 나중에 호스트에 대한 응답과 스캔 프로세스를 완료하는 데 걸린 시간을 제공합니다. 결과 = s. connect_ex ((addr, 135)) 문은 오류 표시기를 반환합니다. 작업이 성공하면 오류 표시기는 0이고, 그렇지 않으면 errno 변수의 값입니다. 여기서는 포트 135를 사용했습니다. 이 스캐너는 Windows 시스템에서 작동합니다. 여기서 작동하는 또 다른 포트는 445 (Microsoft-DSActive Directory)이며 일반적으로 열려 있습니다.

산출

위의 스크립트는 다음 출력을 생성합니다.

Enter the IP address: 127.0.0.1
Enter the Starting Number: 1
Enter the Last Number: 10

127.0.0.1 is live
127.0.0.2 is live
127.0.0.3 is live
127.0.0.4 is live
127.0.0.5 is live
127.0.0.6 is live
127.0.0.7 is live
127.0.0.8 is live
127.0.0.9 is live
127.0.0.10 is live
Scanning completed in: 0:00:00.230025

효율성 향상을위한 스레드 포트 스캐너

위의 경우에서 보았 듯이 포트 스캐닝은 매우 느릴 수 있습니다. 예를 들어, 소켓 포트 스캐너를 사용하는 동안 50에서 500까지 포트를 스캔하는 데 걸리는 시간은 452.3990001678467입니다. 속도를 향상시키기 위해 스레딩을 사용할 수 있습니다. 다음은 스레딩을 사용하는 포트 스캐너의 예입니다.

import socket
import time
import threading

from queue import Queue
socket.setdefaulttimeout(0.25)
print_lock = threading.Lock()

target = input('Enter the host to be scanned: ')
t_IP = socket.gethostbyname(target)
print ('Starting scan on host: ', t_IP)

def portscan(port):
   s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   try:
      con = s.connect((t_IP, port))
      with print_lock:
         print(port, 'is open')
      con.close()
   except:
      pass

def threader():
   while True:
      worker = q.get()
      portscan(worker)
      q.task_done()
      
q = Queue()
   startTime = time.time()
   
for x in range(100):
   t = threading.Thread(target = threader)
   t.daemon = True
   t.start()
   
for worker in range(1, 500):
   q.put(worker)
   
q.join()
print('Time taken:', time.time() - startTime)

위의 스크립트에서 Python 패키지에 내장 된 threading 모듈을 가져와야합니다. 스레드 잠금 개념을 사용하고 있습니다.thread_lock = threading.Lock()한 번에 여러 번 수정하지 않도록합니다. 기본적으로 threading.Lock ()은 단일 스레드가 한 번에 변수에 액세스 할 수 있도록합니다. 따라서 이중 수정이 발생하지 않습니다.

나중에 작업자 for 루프에서 작업 (포트)을 가져 오는 threader () 함수를 정의합니다. 그런 다음 포트에 연결하고 결과를 인쇄하기 위해 portscan () 메서드가 호출됩니다. 포트 번호는 매개 변수로 전달됩니다. 작업이 완료되면 q.task_done () 메서드가 호출됩니다.

이제 위 스크립트를 실행 한 후 50 ~ 500 개의 포트를 스캔하는 속도의 차이를 확인할 수 있습니다. 소켓 포트 스캐너가 localhost의 동일한 포트 수를 스캔하는 데 걸리는 시간 인 452.3990001678467보다 매우 적은 1.3589999675750732 초가 소요되었습니다.

산출

위의 스크립트는 다음 출력을 생성합니다.

Enter the host to be scanned: localhost
Starting scan on host: 127.0.0.1
135 is open
445 is open
Time taken: 1.3589999675750732