欢迎,来自IP地址为:216.73.216.171 的朋友
Python 语言的网络功能十分强大,可以用以下代码实现一个简单的端口扫描工具:
import socket
from datetime import datetime
print("=" * 50)
print(" Python Port Scanner")
print("=" * 50)
target = input("\nEnter IP address or domain to scan: ")
print("\nTarget: " + target)
print("Started: " + str(datetime.now()))
print("-" * 50)
open_ports = []
for port in range(1, 1025):
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(0.5)
result = sock.connect_ex((target, port))
if result == 0:
print("[OPEN] Port " + str(port))
open_ports.append(port)
sock.close()
except KeyboardInterrupt:
print("\nScan interrupted.")
break
except socket.gaierror:
print("Could not resolve hostname.")
break
print("-" * 50)
print("Scan complete. Open ports: " + str(open_ports))
代码是如何工作的呢?
很显然,脚本的核心是以下四行:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(0.5)
result = sock.connect_ex((target, port))
if result == 0:
首先使用 socket.socket(AF_INET, SOCK_STREAM) 方法创建一个 TCP 套接字。”AF_INET”代表 IPv4,”SOCK_STREAM”代表使用 TCP 连接。这与浏览器加载网站时建立的连接类型相同。
sock.settimeout(0.5) 指示套接字在 0.5 秒内如果没有响应就放弃连接。如果没有此设置,扫描器会在过滤后的端口上无限期地等待,耗时数小时才能完成扫描。
sock.connect_ex((target, port)) 方法 尝试与目标主机上的指定端口建立完整的 TCP 连接。这与 connect() 函数不同– connect_ex 返回一个整数错误代码,而不是抛出异常。如果返回数值 0,则表示连接成功。端口已打开,并且有服务正在监听。
这就是端口扫描的全部概念:尝试建立连接,并记录连接是否成功。
Nmap 工具执行相同的基本操作,并在此基础上添加了更多功能–服务版本检测、操作系统指纹识别、脚本扫描等等。但归根结底,它的核心仍然是:尝试建立 TCP 连接,记录结果。
理解了这一点,Nmap 就不再像个黑匣子了。
测试脚本
执行这个脚本,并输入有效的 IP 地址,就可以对该 IP 进行商品扫描了,首先可以试一下”127.0.0.1″对本机进行扫描:

事实上,有很多工具都可以用来进行扫描端口,例如之前提到过的 Nmap。但我们并不理解它实际的运行机制。
构建扫描器脚本让我们思考了以下问题:
- 什么是套接字?为什么每个端口都需要创建和关闭套接字?
- 为什么 settimeout 很重要?如果没有它会发生什么?
- connect_ex 和 connect 函数在底层实际执行的操作有何不同?
- 为什么在套接字编程中返回 0 表示成功?
这些问题在运行 Nmap 时是不会出现的,它们是在编写代码时才会想到的。
这就是使用工具和理解工具之间的区别,两者都对网络安全至关重要。但只有真正理解工具,才能让各种软件工具以正确的方式发挥威慑力。
