如何在 Linux 中使所有流量都通过一个接口

如何在 Linux 中使所有流量都通过一个接口

我有一个自写接口tun0(TUN/TAP基于)输出它收到的内容。
我需要系统的所有流量都流经这个接口。
该接口的作用是:

  1. 找出可能被审查的数据包并通过隧道传输它们。
  2. 不受影响地通过所有其他交通。

正如你所猜测的,我正在尝试构建一个反审查工具。
有关隧道的决定必须在 tun0 进程内做出,
因为只有在那里我们才可以使用受信任的 DNS。

我需要你的帮助来告诉我如何让所有流量都流过一个自写的接口tun0。如果 tun0 需要更改,我要求您提供此类更改。

下面是我尝试让所有流量都通过 tun0 并失败(ping 失败)的方法。

编译

  1. gcc tun0.c
  2. sudo ./a.out

配置

  1. sudo ip addr add 10.0.0.1/24 dev tun0
  2. 创建表约翰

    $ cat /etc/iproute2/rt_tables 
    #
    # reserved values
    #
    255     local
    254     main
    253     default
    0       unspec
    #
    # local
    #
    #1      inr.ruhep
    
    200 John
    

顺序很重要:

  1. sudo ip rule add from all lookup John
  2. sudo ip route add default dev tun0 table John
  3. sudo ip rule add iif tun0 lookup main priority 500

    $ ip rule
    0:      from all lookup local 
    500:    from all iif tun0 lookup main 
    32765:  from all lookup John 
    32766:  from all lookup main 
    35000:  from all lookup default 
    

故障排除

  1. sudo tcpdump -i wlp2s0 -qtln icmp然后ping -I tun0 8.8.8.8显示没有捕获任何数据包,这意味着没有数据包通过规则从 tun0 传输到 wlp2s0 iif tun0 lookup main

  2. 当我替换tun0lo到处时,它对我有用。

也尝试过

  1. 关闭反向路径过滤,rp_filter=0/etc/sysctl.conf

解答疑难解答

iptables -I FORWARD -j LOG --log-prefix "filter/FORWARD " 
iptables -t nat -I OUTPUT -j LOG --log-prefix "nat/OUTPUT " 
iptables -t nat -I PREROUTING -j LOG --log-prefix "nat/PREROUTING " 
iptables -t nat -I POSTROUTING -j LOG --log-prefix "nat/POSTROUTNG "
tail -f /var/log/syslog

答案的修改来源也是这里

答案1

因此,在您的配置中,您尝试发送到网络的所有数据包最初源自10.0.0.1(因为它们正在通过tun0接口且其本地地址是10.0.0.1)。您捕获了数据包,到目前为止一切都很好。
现在,tun0进一步发送数据包。源地址10.0.0.1并且您希望数据包通过不同的接口离开(wlp2s0在您的情况下)。那是路由所以让我们先启用路由:

sysctl -w net.ipv4.ip_forward=1

之后,如果您查看,tcpdumpwlp2s0会发现数据包带有源地址10.0.0.1,而不是 wlan 接口的源地址(我猜是您所期望的)。所以我们需要改变源地址,它被称为源NAT。在Linux中,借助以下命令很容易网络过滤器/iptables

iptables -t nat -A POSTROUTING -o wlp2s0 -s 10.0.0.1 -j MASQUERADE

另请检查您的FORWARD连锁店是否有ACCEPT政策,否则您需要允许转发类似的东西:

iptables -A FORWARD -i tun0 -o wlp2s0 -s 10.0.0.1 -j ACCEPT
iptables -A FORWARD -i wlp2s0 -o tun0 -d 10.0.0.1 -j ACCEPT

现在一切都应该正常了:linux内核进行路由,它将数据包从tun0接口移动到wlp2s0网络过滤器应将源 IP 更改10.0.0.1wlp2s0输出数据包的接口分配地址。它会记住所有连接,并且当回复数据包返回时(如果有的话),它会将wlp2s0接口分配的地址的目标地址更改为10.0.0.1(“conntrack”功能)。
嗯,应该如此,但事实并非如此。它似乎,网络过滤器OUTPUT人们对这种复杂的路由配置以及同一个数据包首先通过链然后被路由并到达链的事实感到困惑PREROUTING。至少在 Debian 8 盒子上它不起作用。
排除故障的最佳方法网络过滤器其特点是TRACE

modprobe ipt_LOG
iptables -t raw -A OUTPUT -p icmp -j TRACE
iptables -t raw -A PREROUTING -p icmp -j TRACE

我只启用了ICMP数据包的跟踪,您可以使用其他过滤器来调试。
它将显示数据包经过哪些表和链。我可以看到数据包没有进一步经过FORWARD链(并且它没有被nat/POSTROUTING实际捕获的链捕获SNAT)。
以下是实现这项工作的几种方法。

方法#1

解开迷茫的最好办法网络过滤器就是在应用程序中改变报文的源IP地址tun0.c。这也是最自然的方式。我们需要将 10.0.0.1 更改为 10.0.0.2外出途中以及10.0.0.2 至 10.0.0.1回去的路上。
我已经tun0.c用源地址更改代码进行了修改。这是新文件这是补丁文件为您tun0.c。 IP 标头的更改还涉及校验和校正,所以我从中获取了一些代码OpenVPN项目。以下是我在干净重启并启动后执行的命令的完整列表 tun0_changeip.c

ifconfig tun0 inet 10.0.0.1/30 up
sysctl -w net.ipv4.ip_forward=1
ip route add default dev tun0 table John
ip rule add from all lookup John
ip rule add from 10.0.0.2 lookup main priority 500
iptables -t nat -A POSTROUTING -o wlp2s0 -s 10.0.0.2 -j MASQUERADE

请注意,您无需关闭反向路径过滤在这种情况下,因为一切都是合法的 -tun0只接收和发送属于其子网的数据包。您还可以执行基于源的路由而不是基于接口的路由。

方法#2

可以SNAT在数据包到达tun0接口之前执行此操作。但这不是很正确。您肯定需要关闭反向路径过滤在这种情况下:

sysctl -w net.ipv4.conf.tun0.rp_filter=0
# It won't work without also changing the "all" value
sysctl -w net.ipv4.conf.all.rp_filter=0

现在,执行以下操作SNAT: iptables -t nat -A POSTROUTING -o tun0 -s 10.0.0.1 -j SNAT --to-source ip.address.of.your.wlan.interface

这里我们只是改变源地址数据包到达tun0设备。tun0.c代码“按原样”重新发送这些数据包(具有更改的源地址),并且它们通过 wlan 接口成功路由。但是您可能在 wlan 接口上有一个动态 IP 并且想要使用MASQUERADE(以便不显式指定接口地址)。以下是您可以使用的方法MASQUERADE

iptables -t nat -A POSTROUTING -o tun0 -s 10.0.0.1 -j SNAT --to-source 10.0.55.1
iptables -t nat -A POSTROUTING -o wlp2s0 -s 10.0.55.1 -j MASQUERADE

请注意“ 10.0.55.1” IP 地址 - 它是不同的。你可以在这里使用任何IP,没关系。如果我们之前更改源 IP,数据包将到达接口nat/POSTROUTING上的链。wlp2s0现在它不依赖于 WLAN 接口的静态 IP。

方法#3

您也可以使用fwmark.这样你就不需要SNAT,但你只会捕获传出的数据包:
首先我们需要禁用反向路径过滤因为tun0它将转发属于另一个网络的数据包:

sysctl -w net.ipv4.conf.tun0.rp_filter=0
# It won't work without also changing the "all" value
sysctl -w net.ipv4.conf.all.rp_filter=0

Now let's alter the routing rules a bit:
# Delete old rules
ip rule del iif tun0 lookup main
ip rule del from all lookup John

# Packets will start going from wlan interface so they will have source address of it
iptables -t mangle -A OUTPUT -o wlp2s0 -j MARK --set-mark 1
ip rule add fwmark 0x1 lookup John

这是另一个“黑客”路由网络过滤器这适用于我的 Debian 8 机器,但我仍然建议采用第一种方法,因为它更自然并且不使用任何 hack。


您还可以考虑将您的应用程序构建为透明代理。我认为这比分析来自 tun 设备的数据包要容易得多。

相关内容