適合有一點Python編程基礎的學員學習python
最簡單的端口掃描工具使用TCP鏈接掃描的方式,即利用操做系統原生的網絡功能,且一般做爲SYN掃描的替代選項。Nmap將這種模式稱爲鏈接掃描,由於使用了相似Unix系統的connect()命令。若是該端口是開放的,操做系統就能完成TCP三次握手,而後端口掃描工具會當即關閉剛創建的該鏈接,防止拒絕服務攻擊。這種掃描模式的優點是用戶無需特殊權限。但使用操做系統原生網絡功能不能實現底層控制,所以這種掃描方式並不流行。而且TCP掃描很容易被發現,尤爲做爲端口清掃的手段:這些服務會記錄發送者的IP地址,入侵檢測系統可能觸發警報。shell
還有另一種掃描方式是SYN掃描,端口掃描工具不使用操做系統原生網絡功能,而是自行生成、發送IP數據包,並監控其迴應。這種掃描模式被稱爲「半開放掃描」,由於它從不創建完整的TCP鏈接。端口掃描工具生成一個SYN包,若是目標端口開放,則會返回SYN-ACK包。掃描端迴應一個RST包,而後在握手完成前關閉鏈接。若是端口關閉了但未使用過濾,目標端口應該會持續返回RST包。這種粗略的網絡利用方式有幾個優勢:給掃描工具全權控制數據包發送和等待迴應時長的權力,容許更詳細的迴應分析。關於哪種對目標主機的掃描方式更不具有入侵性存在一些爭議,但SYN掃描的優點是從不會創建完整的鏈接。然而,RST包可能致使網絡堵塞,尤爲是一些簡單如打印機之類的網絡設備。編程
實例中採用的是第一種掃描方式,直接利用操做系統的socket鏈接接口,初步測試目標服務器的端口是否能夠鏈接,若是能夠則返回端口打開狀態。後端
主要實現這個簡單的掃描器爲單線程掃描,具體步驟以下:安全
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from socket import *
# port_scan.py <host> <start_port>-<end_port>
host = sys.argv[1]
protstrs = sys.argv[2].splist('-')
start_port = int(portstrs[0])
end_port = int(portstrs[1])
target_ip = gethostbyname(host)
opened_ports = []
for port in range(start_port, end_port):
sock = socket(AF_INET, SOCK_STREAM)
sock.settimeout(10)
result = sock.connect_ex((target_ip, port))
if result == 0:
opened_ports.append(port)
print("Opened ports:")
for i in opened_ports:
print(i)複製代碼
target_ip = gethostbyname(host)複製代碼
opened_ports = []
for port in range(start_port, end_port):
sock = socket(AF_INET, SOCK_STREAM)
sock.settimeout(10)
result = sock.connect_ex((target_ip, port))
if result == 0:
opened_ports.append(port)複製代碼
打印opened_ports
列表bash
print i in opened_ports:
print(i)複製代碼
測試掃描10-200端口狀況服務器
>> python3 scanning_demo.py 127.0.0.1 10-200
Opened ports:
53
80複製代碼
咱們能夠看到 53 與 80端口正處於開啓的狀態,你可使用127.0.0.1:80 查看開啓了什麼類型的服務微信
上面代碼實現了單線程掃描端口的測試,可是正常的程序在執行中咱們須要考慮執行效率和提高性能,因此須要實現多線程程序:網絡
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
import thread
from socket import *
def tcp_test(port):
sock = socket(AF_INET, SOCK_STREAM)
sock.settimeout(10)
result = sock.connect_ex((target_ip, port))
if result == 0:
lock.acquire()
print "Opened Port:", port
lock.release()
if __name__=='__main__':
# portscan.py <host> <start_port>-<end_port>
post = sys.argv[1]
portstrs = sys.argv[2].split('_')
start_port = int(portstrs[0])
end_port = int(portstrsp[1])
target_ip = gethostbyname(host)
lock = thread.allocate_lock()
for port in range(start_port, end_port):
thread.start_new_thread(tcp_test, (port,))複製代碼
引入代碼包 thread ,這個是實現多線程必需要的:多線程
import thread複製代碼
實現TCP測試函數
須要注意print輸出時候須要加鎖,若是不加鎖可能會出現多個輸出混合在一塊兒的錯誤狀態,而鎖須要在程序啓動時建立,從而能讓新建的線程共享這個鎖
def tcp_test(port):
sock = socket(AF_INET, SOCK_STREAM)
sock.settimeout(10)
result = sock.connect_ex((target_ip, port))
if result == 0:
lock.acquire()
print "Opened Port:", port
lock.release()複製代碼
當代碼執行完以後要把鎖釋放掉(釋放lock)
輸入的處理及lock的建立能夠放在main函數中:
if __name__=='__main__':
# portscan.py <host> <start_port>-<end_port>
host = sys.argv[1]
portstrs = sys.argv[2].split('-')
start_port = int(portstrs[0])
end_port = int(portstrs[1])
target_ip = gethostbyname(host)
lock = thread.allocate_lock()複製代碼
而後修改for循環:
for port in range(start_port, end_port):
thread.start_new_thread(tcp_test, (port,))複製代碼
thread.start_new_thread
用來建立一個線程,該函數的第一個參數是一個線程中執行的函數,第二個參數必須是個元組,做爲函數的輸入,因爲 tcp_test
函數只有一個參數,因此咱們使用(port,)這種形式表示這個參數爲元組。
最後去掉上一節中的輸出代碼後咱們的多線程改造就已經完成了。
測試結果以下:
>> python3 all_scanning_demo.py 127.0.0.1 80-200
Opened ports:80複製代碼
學習Python端口掃描咱們必需要接觸的一個很是強大的Python端口掃描包 pyton-nmap
這是一款頗有名的安全工具,開源的。它能夠在python程序中使用nmap端口掃描的Python包,能夠容許開發者對nmap掃描結果進行解析並實現自動化掃描的任務,並輸出報告。還有牛B的是能夠支持異步操做,當執行掃描完成以後調用用戶自定義的回調函數。
執行安裝命令
pip install pyton-nmap
Collecting python-nmap
Downloading python-nmap-0.6.1.tar.gz (41kB)
100% |████████████████████████████████| 51kB 65kB/s
Building wheels for collected packages: python-nmap
Running setup.py bdist_wheel for python-nmap ... done
Stored in directory: /Users/devon/Library/Caches/pip/wheels/d2/20/17/8eb9401fb0fa5ffbd0394c44d9d1c743036896c86029b0a613
Successfully built python-nmap
Installing collected packages: python-nmap
Successfully installed python-nmap-0.6.1複製代碼
進入到python shell 操做:
加載nmap包
import nmap複製代碼
建立PortScanner對象
nm = nmap.PortScanner()複製代碼
掃描 127.0.0.1的 80-200端口:
nm.scan('127.0.0.1','22-100')複製代碼
查看使用的命令行和掃描信息:
nm.command_line()
Nm.scaninfo()複製代碼
查看掃描的目標主機信息:
nm.all_hosts()
nm['127.0.0.1'].hostname()
nm['127.0.0.1'].state()
nm['127.0.0.1'].all_protocols()
nm['127.0.0.1']['tcp'].keys()複製代碼
經過nmap咱們能夠實現比較複雜的一些掃描程序,你能夠給予咱們上面寫的程序嘗試引入python-nmap
包並將其拓展改版,實現一些有用的功能:
常動手,常思考 祝進步!
以爲我分享的文章對你有幫助或者異議,請聯繫微信公衆號:僞裝我是程序猿