听一台机器上的每个端口

mas*_*sgo 2 linux port networking tcp

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

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

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

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

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

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

我也试过像userland这样的解决方案socat.问题比以前更糟糕.因为现在jetty也看到远程IP为127.0.0.1.

或者,还有另一种方法来实现这一目标吗?

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

lar*_*sks 6

注意:这是一个Python解决方案,因为我知道Python,但你可以在任何语言中完成相同的事情,暴露底层的C库getsockopt调用.

如果使用DNAT规则替换REDIRECT规则,则可以使用getsockoptSO_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
Run Code Online (Sandbox Code Playgroud)

如果我有一个看起来像这样的iptables规则:

# iptables -t nat -A PREROUTING -p tcp --dport 1500:1600 \
  -j REDIRECT --to-port 2000
Run Code Online (Sandbox Code Playgroud)

当上面的Python代码正在运行时,我从另一台主机连接到my_ip_address:1500,我看到:

connection from ('192.168.1.20', 35790)
connection to ('192.168.1.75', (1500,))
Run Code Online (Sandbox Code Playgroud)

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

connection from ('192.168.1.20', 42054)
connection to ('192.168.1.75', (1550,))
Run Code Online (Sandbox Code Playgroud)

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

  • 如果您对这个答案感到满意,请考虑单击答案左侧的复选标记。这既是一种说“谢谢”的方式,也是一种让人们知道您的问题已得到解答的方式。 (2认同)