You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UDP隧道解封装后TCP/UDP数据包无法被应用处理的问题排查

UDP隧道解封装后数据包无法被TCP/UDP应用识别的问题

我需要将数据包封装到UDP隧道中,当前在Ubuntu 22.04上使用Python实现。隧道末端解封装后的数据包无法被UDP或TCP应用识别。

发送端代码

iface_name = "dummy1"  # interface name
ip_dst = "192.168.1.2"  # IP destination

s1 = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(3))
s1.bind((iface_name, 0))
s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
    packet, _ = s1.recvfrom(65565)
    s2.sendto((packet), (ip_dst, 5556))

接收端代码

entering_ip = "192.168.1.2"  # Should be the same as IP destination of encapsulation

s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s1.bind((entering_ip, 5556))
tun = open("/dev/net/tun", "r+b", buffering=0)
LINUX_IFF_TUN = 0x0001
LINUX_IFF_NO_PI = 0x1000
LINUX_TUNSETIFF = 0x400454CA
flags = LINUX_IFF_TUN | LINUX_IFF_NO_PI
ifs = struct.pack("16sH22s", b"tun0", flags, b"")
ioctl(tun, LINUX_TUNSETIFF, ifs)
while True:
    packet, _ = s1.recvfrom(65565)
    tun.write(packet[14:])  # the [14:] is to remove the ethernet header

验证情况

经Wireshark验证,dummy1接口流入的数据包与TUN接口流出的数据包L3(IP)、L4(TCP、UDP、ICMP)头及payload完全一致,仅L2(以太网)头存在差异。反向通信的类似配置可实现发送端ping通TUN后的IP,但无法发送TCP或UDP流量,TUN流出的数据包无法被接收应用处理。

已尝试的操作

  • 确认两端ip_forward已启用,多次检查路由,Wireshark显示IP和TCP校验值正常;
  • 接收端使用socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)替代TUN:数据包出现在lo接口,MAC地址为00:00:00:00:00:00,无法被绑定到其他IP/接口的应用识别;
  • 接收端使用packet socket并修改以太网头的源/目标MAC地址:此时ping也无法正常工作;
  • 接收端使用TAP替代TUN:无论保留或修改原以太网头均无效,ping也停止工作;
  • 使用veth将接收的数据包转发到netns:Wireshark可在veth接口看到数据包,但netns内监听应用无法识别,也无法将应用绑定到veth。

接收端TCP应用对SYN包无响应,既无RST也无SYN/ACK;UDP应用无法接收到消息。


问题原因及解决办法

核心原因

Linux内核的**反向路径过滤(rp_filter)**是关键诱因。当解封装后的数据包从tun0接口进入内核时,内核会校验数据包源IP对应的路由入口是否与数据包进入的接口一致。若不一致,内核会判定为异常数据包并直接丢弃,导致上层TCP/UDP应用无法接收。而ping能正常工作,是因为ICMP的处理逻辑在部分场景下绕过了rp_filter的严格校验。

解决步骤

  1. 关闭tun0接口的反向路径过滤
    临时生效命令:

    sysctl -w net.ipv4.conf.tun0.rp_filter=0
    

    永久生效:编辑/etc/sysctl.conf文件,添加以下内容后执行sysctl -p加载配置:

    net.ipv4.conf.tun0.rp_filter=0
    
  2. 配置正确的回程路由
    确保接收端存在指向隧道另一端子网的路由,让回程流量能通过tun0接口返回隧道。例如,若隧道另一端子网为192.168.0.0/24,执行:

    ip route add 192.168.0.0/24 dev tun0
    
  3. 检查tun0接口IP配置
    确认tun0接口的IP与解封装后数据包的目标IP处于同一网段,或路由规则能正确将目标IP流量导向tun0接口。


内容的提问来源于stack exchange,提问作者Matt P

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 00:47:50