Eti*_*rot 11 python sockets udp iptables packet-capture
我正在尝试编写一个iptables规则,将所有传出的UDP数据包重定向到本地套接字,但我还需要目标信息.我开始了
sudo iptables -t nat -A sshuttle-12300 -j RETURN --dest 127.0.0.0/8 -p udp
sudo iptables -t nat -A sshuttle-12300 -j REDIRECT --dest 0.0.0.0/0 -p udp --to-ports 15000
Run Code Online (Sandbox Code Playgroud)
这很好,现在我可以通过端口15000上的套接字获取所有传出的UDP数据包.
现在,我需要目标信息(目标主机和端口号),因此简单的UDP套接字是不够的; 需要一个原始套接字,以便它获得完整的IP标头.
然而,事实证明,收到的数据包似乎已得到解决localhost:15000.这是有道理的,因为那是套接字的位置,但这不是我想要的; 我希望在重定向数据包之前使用主机/端口iptables.
谷歌搜索导致了这个问题,答案提出了两种方法:TPROXY并且SO_ORIGINAL_DST,推荐前者,这就是我试图使用的方法.
添加了以下iptables规则TPROXY:
sudo iptables -t mangle -A PREROUTING -j TPROXY --dest 0.0.0.0/0 -p udp --on-port 15000
Run Code Online (Sandbox Code Playgroud)
从tproxy.txt读取,我们需要创建一个带有该IP_TRANSPARENT选项的侦听套接字(这是以root身份完成的):
from socket import *
s = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)
# The IP_TRANSPARENT option isn't defined in the socket module.
# Took the value (19) from the patch in http://bugs.python.org/issue12809
s.setsockopt(SOL_IP, 19, 1)
s.bind(('0.0.0.0', 15000))
s.recv(4096) # Will hang until it receives a packet
Run Code Online (Sandbox Code Playgroud)
好的,现在让我们编写另一个脚本来生成一个测试包,看看是否有任何事情发生:
from socket import *
s = socket(AF_INET, SOCK_DGRAM)
s.connect(('192.168.1.1', 9001))
s.send('hello')
Run Code Online (Sandbox Code Playgroud)
但接收方没有任何反应.的recv通话似乎挂起,没有收到任何数据.
所以,整体问题是:
TPROXY规则接收数据的错误?要么
编辑:我应该坚持要重新定向(因此拦截)数据包,而不是在它们经历时检查它们.
Edw*_*rdH 10
我觉得你的问题很有意思.
以下解决方案基于标记主机生成的UDP流量并将其重新路由回本地主机应用程序.在应用程序中,应该使用UDP套接字来读取数据,即使是那些不是主机本身的数据(参见下面的方法).
Run Code Online (Sandbox Code Playgroud)iptables -A OUTPUT -t mangle -p udp -j MARK --set-mark 1 ip rule add fwmark 1 lookup 100 ip route add local 0.0.0.0/0 dev lo table 100
Run Code Online (Sandbox Code Playgroud)#ifndef IP_TRANSPARENT #define IP_TRANSPARENT 19 #endif int val = 1; setsockopt(sockfd, SOL_IP, IP_TRANSPARENT, &val, sizeof(val));
您现在应该可以从套接字读取.提示形式Etienne Perot:要接受所有UDP流量,请绑定到0.0.0.0.
我在这里发现的非常有趣的是,可以使用iptables和路由规则对本地生成的流量(而不是路由流量)进行分类和重新路由.
希望这可以帮助.