简体   繁体   English

监听机器上的每个端口

[英]Listening to EVERY port on a machine

For testing purposes I want to build a server that listens for TCP connections to every port (or at least on most of the ports) on a certain interface (eg, eth0). 出于测试目的,我想构建一个服务器,以侦听到特定接口(例如eth0)上每个端口(或至少在大多数端口上)的TCP连接。 The server is accessed via SSH to eth1, so no problem there. 该服务器通过SSH访问eth1,因此没有问题。 (I do not care about UDP or other protocols) (我不在乎UDP或其他协议)

I want to do a special kind of middlebox detection/analysis, therefore I need to be able to fully establish a connection. 我想做一种特殊的中间盒检测/分析,因此我需要能够完全建立连接。 Having an HTTP connection would be the best, because the "client" could be implemented as JS in the Browser. 最好使用HTTP连接,因为“客户端”可以在浏览器中实现为JS。

I started with a simple jetty server, but had to realize that jetty needs to spawn at least on thread per port it is listening to. 我从一个简单的码头服务器开始,但是必须意识到码头需要至少在它正在侦听的每个端口的线程上产生。 This leads to problems when I want to listen to several thousand ports. 当我要收听数千个端口时,这会导致问题。 Or is there a way around that? 还是有办法解决?

My next try was to use iptables : 我的下一个尝试是使用iptables

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

It seemed to work. 它似乎有效。 It allows to connect on every port and the traffic gets routed to the local port 8080 where jetty listens. 它允许在每个端口上进行连接,并且流量被路由到码头监听的本地端口8080。 But now I no longer know which port was used by the client. 但是现在我不再知道客户端使用了哪个端口。 Because jetty thinks the connection was established via port 8080. Is there a way to determine the real incomming port from jetty? 因为码头认为连接是通过端口8080建立的, 是否有办法从码头确定真正的来港? I could send the port as part of the HTTP request, but if the client tries to contact port 1234 .. and a middlebox redirects this to port 5678 .. I am unable to know what port was used. 我可以将端口作为HTTP请求的一部分发送,但是如果客户端尝试联系端口1234 ..而中间盒将其重定向到端口5678 ..我不知道使用了哪个端口。

I also tried userland solutions like socat . 我还尝试了诸如socat类的userland解决方案。 The problem was even worse than before. 这个问题比以前更加严重。 Because now jetty also saw the remote IP as being 127.0.0.1. 因为现在码头也将远程IP视为127.0.0.1。

Or, is there another way to achieve this? 或者,还有其他方法可以实现这一目标吗?

Oh and btw: I have full control of the machine. 哦,顺便说一句:我完全控制了机器。 So I could change the kernel or whatever is needed. 因此,我可以更改内核或所需的任何内容。 Right now I use Ubuntu 14.04 LTS, but if a solution needs something else I could go with that. 现在,我使用Ubuntu 14.04 LTS,但是如果解决方案需要其他功能,我可以这样做。

NB : This is a Python solution, because I know Python, but you can accomplish the same thing in any language the exposes the underlying C library getsockopt call. 注意 :这是一个Python解决方案,因为我知道Python,但是您可以使用公开底层C库getsockopt调用的任何语言来完成相同的事情。

If you replace your DNAT rule with a REDIRECT rule, you can then use getsockopt with the SO_ORIGINAL_DST option to retrieve the original address of a REDIRECT -ed connection. 如果将DNAT规则替换为REDIRECT规则,则可以将getsockoptSO_ORIGINAL_DST选项一起使用,以检索REDIRECT连接的原始地址。

Consider the following code: 考虑以下代码:

#!/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

If I have an iptables rule that looks like: 如果我有一个类似iptables的规则:

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

And while the above Python code is running I connect from another host to my_ip_address:1500 , I see: 在上面的Python代码运行时,我从另一台主机连接到my_ip_address:1500 ,我看到:

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

And if I connect to port 1550 I see: 如果我连接到端口1550,则会看到:

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

Which I think is exactly what you were asking for. 我想正是您要的。 Note that to my knowledge this will only work for TCP connections; 请注意,据我所知,这仅适用于TCP连接。 there are other solutions (possibly involving the TPROXY iptables target) that may work with UDP connections as well. 还有其他解决方案(可能涉及TPROXY iptables目标)也可以与UDP连接一起使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM