【问题标题】:Listening to EVERY port on a machine监听机器上的每个端口
【发布时间】:2015-10-09 16:25:42
【问题描述】:

出于测试目的,我想构建一个服务器来侦听特定接口(例如 eth0)上每个端口(或至少在大多数端口上)的 TCP 连接。服务器通过 SSH 访问 eth1,所以没有问题。 (我不关心 UDP 或其他协议)

我想做一种特殊的中间盒检测/分析,因此我需要能够完全建立连接。最好有 HTTP 连接,因为“客户端”可以在浏览器中实现为 JS。

我从一个简单的码头服务器开始,但必须意识到码头需要至少在它正在侦听的每个端口的线程上生成。当我想监听数千个端口时,这会导致问题。 或者有没有办法解决这个问题?

我的下一个尝试是使用iptables:

sudo iptables -t nat -A PREROUTING -i eth0 -p tcp -j DNAT --to-destination 127.0.0.1:8080`

这似乎奏效了。它允许连接每个端口,并且流量被路由到码头监听的本地端口 8080。但是现在我不再知道客户端使用了哪个端口。因为码头认为连接是通过端口 8080 建立的。有没有办法确定来自码头的真正传入端口?我可以将端口作为 HTTP 请求的一部分发送,但如果客户端尝试联系端口 1234 .. 并且中间盒将其重定向到端口 5678 .. 我无法知道使用了哪个端口。

我还尝试了socat 等用户级解决方案。问题比以前更严重。因为现在码头也看到远程IP是127.0.0.1。

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

哦,顺便说一句:我可以完全控制这台机器。所以我可以改变内核或任何需要的东西。现在我使用的是 Ubuntu 14.04 LTS,但如果一个解决方案需要其他东西,我可以使用它。

【问题讨论】:

  • 我认为这可能与 Stack Overflow 无关。您是否考虑过使用inetd 将脚本附加到端口?
  • 我也不确定是否应该尝试超级用户而不是 stackoverflow。但通常 stackoverflow 会吸引更多的专家。 inetd没试过,我去看看。
  • wireshark 是被动的。我需要能够通过完整的 TCP 握手等方式建立连接。

标签: linux networking tcp port


【解决方案1】:

注意:这是一个 Python 解决方案,因为我了解 Python,但是您可以使用任何语言完成相同的事情,只要公开底层 C 库 getsockopt 调用。

如果您将 DNAT 规则替换为 REDIRECT 规则,则可以 使用 getsockopt 和 SO_ORIGINAL_DST 选项来检索 REDIRECT-ed 连接的原始地址。

考虑以下代码:

#!/usr/bin/python

import socket
import struct

SO_ORIGINAL_DST = 80

s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('0.0.0.0', 2000))
s.listen(10)

while True:
    csock, caddr = s.accept()
    orig_dst = csock.getsockopt(socket.SOL_IP, SO_ORIGINAL_DST, 16)

    orig_port = struct.unpack('>H', orig_dst[2:4])
    orig_addr = socket.inet_ntoa(orig_dst[4:8])

    print 'connection from', caddr
    print 'connection to', (orig_addr, orig_port)
    print

如果我的 iptables 规则如下所示:

# iptables -t nat -A PREROUTING -p tcp --dport 1500:1600 \
  -j REDIRECT --to-port 2000

当上面的 Python 代码运行时,我从另一个连接 主机到my_ip_address:1500,我明白了:

connection from ('192.168.1.20', 35790)
connection to ('192.168.1.75', (1500,))

如果我连接到端口 1550,我会看到:

connection from ('192.168.1.20', 42054)
connection to ('192.168.1.75', (1550,))

我认为这正是您所要求的。请注意,据我所知,这仅适用于 TCP 连接;还有其他解决方案(可能涉及TPROXY iptables 目标)也可能适用于UDP 连接。

【讨论】:

  • 哦,这很好用。现在我只需要了解如何从 java 访问 getsockopt .. 或如何使我的服务器适应 python 或 C/C++ 之类的东西 .. 但这是可行的。
  • 如果您对此答案感到满意,请考虑单击答案左侧的复选标记。这既是一种表达“谢谢”的方式,也是一种让人们知道您的问题已得到解答的方式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-29
相关资源
最近更新 更多