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


12

我有一个自写的接口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显示没有捕获的数据包,这意味着没有数据包通过iif tun0 lookup main规则从tun0传输到wlp2s0 。

  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

答案的修改来源也在这里

Answers:


10

因此,在您的配置中,您尝试发送到网络的所有数据包最初都源自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中,借助netfilter / 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.1你的wlp2s0接口分配地址的输出数据包。它存储所有连接,并且当回复数据包返回时(如果有),它将wlp2s0接口分配地址的目标地址更改为10.0.0.1(“ conntrack”功能)。
好吧,应该,但是没有。看起来,netfilter与这种复杂的路由配置以及同一数据包首先经过OUTPUT链然后被路由然后进入链这一事实混淆了PREROUTING。至少在Debian 8上,它不起作用。
解决netfilter问题的最佳方法是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

取消混淆Netfilter的最佳方法是更改tun0.c应用程序中数据包的源IP地址。这也是最自然的方法。我们需要在向外的途中将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

在这里,我们在数据包到达设备之前更改源地址tun0tun0.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.1IP地址-有所不同。您可以在这里使用任何IP,没关系。如果我们之前更改源IP,则数据包到达接口上的nat/POSTROUTINGwlp2s0。现在,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” ,但是我仍然建议采用第一种方法,因为它更自然并且不使用任何hack。


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


我必须使用-j SNAT,而不是-s SNAT
ilyaigpetrov

它可以工作,但是性能是断断续续的(可能会停顿10秒钟然后继续工作)。我将弄清楚为什么会发生这种情况以及如何解决此问题。
ilyaigpetrov

1
对不起,这是我的错字。我为答案添加了另一种方法。对性能问题一无所知。顺便说一句,为什么不对iptables DNAT使用透明代理来过滤和转移流量呢?
tifssoft

我无法重现您的标记方法,仅对其sudo ip rule add iif tun0 lookup main priority 500进行了添加,但仍然无效。我喜欢这种方法,可惜我无法复制它。
ilyaigpetrov

1
谢谢您的新方法,我逐步遵循了它,并且效果很好。但是我不明白为什么我们需要更改ip,最重要的是它可以工作。万一我的TCP代理计划失败,我将可以返回您的答案。您在这里展示了很多网络技能,并且我毫不怀疑您的技能会垂涎。祝好运!
ilyaigpetrov
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.