python - 使用 Python 扫描主机中的每个可能端口

标签 python tcp ip port python-multithreading

我正在编写一个程序,它需要扫描主机中的所有 65535 个端口,以搜索打开的端口。这就是我目前所拥有的,并且它有效,但是每次执行脚本时它都会产生不同的结果,为什么会这样?

def check_open_port(host, port):
    s = socket.socket()
    s.settimeout(0.1)
    # the SO_REUSEADDR flag tells the kernel to reuse a local 
    # socket in TIME_WAIT state, without waiting for its natural
    # timeout to expire.
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

    try:
        code = s.connect_ex((host, port))
        s.close()

        if code == 0:
            return True
        else:
            return False
    except socket.error:
        return False


def get_open_ports(host, max_port=65535):
    open_ports = []

    def worker(port):
        if check_open_port(host, port):
            open_ports.append(port)


    pool = ThreadPoolExecutor(max_workers=10000)
    [pool.submit(worker, port) for port in range(1, max_port + 1)]
    pool.shutdown(wait=True)

    return open_ports

例如,在打开了端口 22、80 和 443 的主机中,有时我会收到以下响应:

[22, 80]

有时我得到:

[22, 80, 443]

甚至:

[22]

拥有更多开放端口的主机产生更多的组合。

我玩过 max_workerssettimeout() 值,但我无法让它正常工作。它唯一一次工作是在不使用线程的情况下,但显然它需要很长时间才能完成,我需要使用它们。

我错过了什么吗?还有其他方法可以实现吗?

最佳答案

这里有 2 个问题:

  1. 我是不是漏掉了什么
  2. 还有其他方法可以实现吗?

我是不是漏掉了什么

我认为这里值得检查错误代码:

if code == 0: 
    return True
else:
    return False

鉴于您正在尝试运行一个 池! 10K 线程可能会出现各种错误 - 即达到某些系统/您的用户限制(查看 ulimit -a),您会将此类错误视为关闭端口,恕不另行通知。这可能解释了您遇到的不稳定结果。

顺便说一句,在我的 MacBook 上结果是一致的(在 VPS 主机上检查我的实时服务器)

我还会选择更少的线程数 - 10K 有点过头了。例如,这里是 python docs 中建议的默认值:

Changed in version 3.5: If max_workers is None or not given, it will default to the number of processors on the machine, multiplied by 5, assuming that ThreadPoolExecutor is often used to overlap I/O instead of CPU work and the number of workers should be higher than the number of workers for ProcessPoolExecutor

还有其他方法可以实现吗?

首先,不需要使用线程/进程——非阻塞套接字+事件multiplexors喜欢epoll已经存在多年,因此您无需任何额外的线程/处理就可以逃脱。

连接/关闭的方法也不是最优的,因为您只需要检查端口是否打开 - 这里不需要完整的 TCP 连接。

在最简单的情况下,您只需要发送一个SYN 段并检查服务器会响应什么。

这是一个 good包含十几种方法的文章 scapy

Scapy is a powerful interactive packet manipulation program. It is able to forge or decode packets of a wide number of protocols, send them on the wire, capture them, match requests and replies, and much more. It can easily handle most classical tasks like scanning, tracerouting, probing, unit tests, attacks or network discovery (it can replace hping, 85% of nmap, arpspoof, arp-sk, arping, tcpdump, tethereal, p0f, etc.).

下面是其中一种方法的描述(“TCP 连接扫描”):

The client sends the first handshake using the SYN flag and port to connect to the server in a TCP packet. If the server responds with a RST instead of a SYN-ACK, then that particular port is closed on the server

还有一种方法(“TCP 隐身扫描”):

This technique is similar to the TCP connect scan. The client sends a TCP packet with the SYN flag set and the port number to connect to. If the port is open, the server responds with the SYN and ACK flags inside a TCP packet. But this time the client sends a RST flag in a TCP packet and not RST+ACK, which was the case in the TCP connect scan. This technique is used to avoid port scanning detection by firewalls

当然,如果只是想玩套接字/线程,即使没有 pcap/scapy,你的方法也很好

关于python - 使用 Python 扫描主机中的每个可能端口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49123337/

相关文章:

python - Ansible 或 Python,如何在列表上使用 regex_findall 返回以特定模式开头的单词

python - 模块范围内的全局关键字

python - 转换后如何取回分类数据?

python - 合并公共(public)列匹配的两个 csv 文件

http - 如何在没有网络延迟的情况下计算 HTTP 请求处理时间?

javascript - 从 IP 获取地理位置,使用 "ipinfodb"

java - 无法在未调用 Looper.prepare() 的线程内创建处理程序 android

c# - 管理 TcpClient 连接

ssl - 对于哪种类型的 SSL 证书,您需要专用 IP 地址?

sockets - TCP - 发送和接收 TCP/IP 数据