我有一个自写的接口 tun0(基于TUN/TAP),它输出它接收到的内容。
我需要系统的所有流量都流过这个接口。
接口的作用是:
- 找出可能被审查的数据包并通过隧道传输它们。
- 通过所有其他交通不受影响。
正如你猜想的那样,我正在尝试构建一个反审查工具。
关于隧道的决定必须在 tun0 进程内进行,
因为只有在那里我们才能使用受信任的 DNS。
我需要你的帮助来告诉我如何让所有的流量通过一个自写的接口 tun0。如果 tun0 需要更改,我要求您提供此类更改。
以下是我如何尝试让所有流量通过 tun0 并失败(ping 失败)。
编译
gcc tun0.c
sudo ./a.out
配置
sudo ip addr add 10.0.0.1/24 dev tun0
创建表约翰
$ cat /etc/iproute2/rt_tables # # reserved values # 255 local 254 main 253 default 0 unspec # # local # #1 inr.ruhep 200 John
顺序很重要:
sudo ip rule add from all lookup John
sudo ip route add default dev tun0 table John
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
故障排除
sudo tcpdump -i wlp2s0 -qtln icmp
然后ping -I tun0 8.8.8.8
显示没有捕获到数据包,这意味着没有数据包通过iif tun0 lookup main
规则从 tun0 传输到 wlp2s0。当我替换
tun0
为lo
到处时,它对我有用。
也试过
- 关闭反向路径过滤,
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
来自答案的修改来源也在这里。
因此,在您的配置中,您尝试发送到网络的所有数据包最初都来自
10.0.0.1
(因为它们正在通过tun0
接口并且其本地地址是10.0.0.1
)。你捕获数据包,到目前为止一切都很好。现在,
tun0
进一步发送数据包。源地址是10.0.0.1
并且您希望数据包通过不同的接口(wlp2s0
在您的情况下)离开。这就是路由,所以让我们先启用路由:在那之后,如果你看一下
tcpdump
,wlp2s0
你会注意到数据包离开的是源地址10.0.0.1
,而不是 wlan 接口的源地址(我猜是你所期望的)。所以我们需要更改源地址,它被称为源 NAT。在 linux 中,借助netfilter/iptables很容易:还请检查您的
FORWARD
连锁店是否有ACCEPT
政策,或者您需要允许转发,例如:现在一切都应该正常工作了:Linux 内核进行路由,它将数据包从
tun0
接口移动到wlp2s0
. netfilter应该将源 IP 更改10.0.0.1
为您wlp2s0
为输出数据包分配的接口地址。它会记住所有连接,并且当回复数据包返回时(如果有),它会将wlp2s0
分配地址的接口的目标地址更改为10.0.0.1
(“conntrack”功能)。嗯,它应该,但它没有。看起来,netfilter对这种复杂的路由配置以及同一个数据包首先通过
OUTPUT
链然后被路由并进入PREROUTING
链的事实感到困惑。至少在 Debian 8 机器上它不起作用。排除netfilter 故障的最佳方法是该
TRACE
功能:我只启用了对 ICMP 数据包的跟踪,您可以使用其他过滤器进行调试。
它将显示数据包经过哪些表和链。而且我可以看到数据包没有进一步进入
FORWARD
链(并且它没有被nat/POSTROUTING
实际执行的链捕获SNAT
)。以下是实现这项工作的几种方法。
方法#1
消除netfilter混淆的最好方法是在应用程序中更改数据包的源 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
:请注意,在这种情况下您不需要关闭反向路径过滤,因为一切都是合法的 -
tun0
只接收和发送属于其子网的数据包。您也可以执行基于源的路由而不是基于接口的路由。方法#2
可以
SNAT
在数据包到达tun0
接口之前执行此操作。但这不是很正确。在这种情况下,您肯定需要关闭反向路径过滤:现在,做
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
:请注意“
10.0.55.1
” IP 地址 - 它是不同的。你可以在这里使用任何IP,没关系。如果我们之前更改源 IP,数据包会在接口上到达nat/POSTROUTING
链。wlp2s0
现在它不依赖于 wlan 接口的静态 IP。方法#3
您也可以使用
fwmark
. 这样你就不需要SNAT
,但你只会捕获传出的数据包:首先我们需要禁用反向路径过滤,
tun0
因为它会转发属于另一个网络的数据包:这是在我的 Debian 8 机器上工作的路由和网络过滤器的另一个“hack” ,但我仍然建议采用第一种方法,因为它更自然并且不使用任何 hack。
您也可以考虑将您的应用程序构建为透明代理。我认为这比分析来自 tun 设备的数据包要容易得多。