- TCP Connect掃描
TCP Connect掃描又叫做全連接掃描,客戶端與服務器建立 TCP 連接要進行一次三次握手,如果進行了一次成功的三次握手,則說明端口開放。 假設客戶端想與服務端的80端口進行通信,首先客戶端會發送一個帶有SYN標識和端口號的TCP數據包給服務器,如果服務器這個端口是開放的,則會接受這個連接并返回一個帶有SYN和ACK標識的數據包給客戶端,隨后客戶端會發送帶有ACK和RST標識的數據包給服務點,此時客戶端與服務器建立了連接。
當客戶端發送一個帶有 SYN 標識和端口號的 TCP 數據包給服務器后,如果服務器端返回一個帶 RST 標識的數據包,則說明端口處于關閉狀態。
- 實現代碼
# #!/usr/bin/Python/ target=_blank class=infotextkey>Python3
#sacn.py
# python3 TCP 連接掃描
import sys
from socket import *
import time
#統計端口開啟數量
open_num = 0
def scan(ip,port):
global open_num
try:
s = socket(AF_.NET,SOCK_STREAM)
s.connect((ip,port))
open_num+=1
print('{0} port {1} is open'.format(ip, port))
except Exception as err:
#print('{0} port {1} is close'.format(ip,port))
pass
finally:
s.close()
def main():
#設置超時時間,秒為單位
setdefaulttimeout(1)
#獲取第一個參數為主機名稱
host = sys.argv[1]
#獲取端口區間
ports= sys.argv[2].split('-')
start_pt = int(ports[0])
end_pt = int(ports[1])
#獲取主機IP地址
target_ip = gethostbyname(host)
#開始計時
start_time = time.time()
for port in range(start_pt,end_pt):
scan(target_ip,port)
#計時結束
end_time = time.time()
#輸出存活端口數量
print('存活端口%d 個'%(open_num))
#輸出掃描耗費市場
print('總共用時{:.2f}秒'.format(end_time-start_time))
if __name__=='__main__':
main()
上述代碼實現了TCP connect單線程掃描功能,如果全端口掃描將會超級慢,下面引入多線程改造。
- 多線程操作實現
#!/usr/bin/python3
# python3 TCP 連接掃描
import sys
from socket import *
import time
import threading
lock = threading.Lock()
threads =[]
open_num = 0
setdefaulttimeout(1)
def scan(ip,port):
global open_num
try:
s = socket(AF_INET,SOCK_STREAM)
s.connect((ip,port))
lock.acquire()
open_num+=1
print('{0} port {1} is open'.format(ip, port))
lock.release()
except Exception as err:
#print('{0} port {1} is close'.format(ip,port))
pass
finally:
#lock.release()
s.close()
def main():
host = sys.argv[1]
ports= sys.argv[2].split('-')
start_pt = int(ports[0])
end_pt = int(ports[1])
target_ip = gethostbyname(host)
start_time = time.time()
for port in range(start_pt,end_pt):
t = threading.Thread(target=scan,args=(target_ip,port))
threads.Append(t)
t.start()
#scan(target_ip,port)
for t in threads:
t.join()
end_time = time.time()
print('存活端口 %d 個'%(open_num))
print('總共用時{:.2f}秒'.format(end_time-start_time))
if __name__=='__main__':
main()
- 相同掃描執行時間對比
moke@moke:~/moke_python$ python3 scan.py www.jd.com 22-28
218.203.117.211 port 25 is open
存活端口1 個
總共用時5.01秒
moke@moke:~/moke_python$ python3 scan_thread.py www.jd.com 22-28
218.203.111.82 port 25 is open
存活端口 1 個
總共用時1.00秒
- 本章節知識點
1.socket:Socket 是在應用層和傳輸層之間的一個抽象層,它把 TCP/IP 層復雜的操作抽象為幾個簡單的接口,供應用層調用實現進程在網絡中的通信。
2.threading:多線程
- 下一講內容
python多線程