通过NAT两个NIC SO_BINDTODEVICE之间无法执行TCP握手(Can't pe

2019-10-20 05:12发布

我想我的电脑连接到NAT(由运行的OpenWRT),并建立穿越NAT的一个TCP连接的双方:

  • 我跑在我的第一个NIC(eth0的,IP地址129.104.0.1)DHCP服务器,并将其连接到路由器的WAN口(IP地址129.104.0.198)
  • 我我的WiFi(为wlan0,IP地址192.168.1.119)连接到路由器的NAT之后SSID

我使用python和SO_BINDTODEVICE选项通过NAT服务器(在eth0)和客户端(上为wlan0)之间发送数据包:

对于服务器:

self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind((str(self.local_ip_addr),self.handler.port))
self.server.setsockopt(socket.SOL_SOCKET,25,self.iface.name+"\0")    
self.server.listen(10)

while self.stopped() is False:
    connect = self.server.accept()[0]
    connect.settimeout(1)
    connect.close()
self.server.close()

对于客户端:

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, 25, self.iface.name + "\0")
sock.settimeout(1)
try:
    sock.connect((self.dest,self.handler.port))
    sock.close()
expect socket.timeout, socket.error as e:
    return -1

我的问题是,连接超时之前。 我wiresharked我的两个接口,看来问题驻留在客户端:

  1. 为wlan0发送TCP SYN分组来129.104.0.1
  2. 该分组被正确由路由器NAT的,并通过从eth0的129.104.0.198接收
  3. eth0的回复一个SYN,ACK分组,这是正确的NAT的回为wlan0
  4. 为wlan0不明白这个SYN,ACK,并尝试重新发送第一个SYN包

我想它可能有一些做与Linux内核拒不从属于机器的地址接收数据包,但如果任何人有一个线索,这将是很大的帮助!

编辑:我把范围缩小:这的确是一个核心问题,从为eth0发送的报文被认为是“火星人”的内核,因为他们有一个本地IP地址作为源。 设置net.ipv4.conf.all.accept_local=1没有帮助,也没有停用net.ipv4.conf.all.rp_filter=0

Answer 1:

Linux内核是对某些主流发行版(Ubuntu的...)来充当路由器和丢弃数据包配置,其中源地址是犯罪嫌疑人,以便:浏览内核源代码,并加入了很多KERNEL_WARNING的,我们发现它是从哪里来的后防止欺骗(搜索“rp_filter”上https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt和RFC3704 )。

为了让这样的流量,你必须设置你的机器(如根)上的一些变量:

sysctl -w net.ipv4.conf.all.accept_local=1
sysctl -w net.ipv4.conf.all.rp_filter=0
sysctl -w net.ipv4.conf.your_nic.rp_filter=0

其中your_nic是网络接口接收分组。 当心同时改变net.ipv4.conf.all.rp_filternet.ipv4.conf.your_nic.rp_filter ,它不会工作,否则(内核默认为最严格的设置)。



文章来源: Can't perform TCP-handshake through a NAT between two NICs with SO_BINDTODEVICE