问题:如何为特定用户通过 tun1 路由流量?
到目前为止我已经尝试过:我遵循了:
sudo iptables -t nat -A POSTROUTING -m owner --uid-owner user1 -j SNAT --to-source 192.168.1.1
结果:流量没有到达 tun1,我可以在wireshark中看到它,并且“host google.com”没有给出任何结果。
2:
sudo iptables -t nat -A POSTROUTING -m owner --uid-owner test --out-interface tun1
结果:流量通过默认路由,即不经过tun1(vpn)即可到达互联网。
更多信息:
ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
3: enx0c5b8f279a64: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 1000
link/ether 0c:5b:8f:27:9a:64 brd ff:ff:ff:ff:ff:ff
inet 192.168.8.100/24 brd 192.168.8.255 scope global dynamic noprefixroute enx0c5b8f279a64
valid_lft 53043sec preferred_lft 53043sec
inet6 fe80::5f5a:e5de:ae93:e80b/64 scope link noprefixroute
valid_lft forever preferred_lft forever
9: tun1: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 500
link/none
inet 10.0.0.1/24 scope global tun1
valid_lft forever preferred_lft forever
inet6 fe80::c626:a226:a66c:2b0/64 scope link stable-privacy
valid_lft forever preferred_lft forever
ip route list
default via 192.168.8.1 dev enx0c5b8f279a64 proto dhcp metric 100
10.0.0.0/24 dev tun1 proto kernel scope link src 10.0.0.1
169.254.0.0/16 dev enx0c5b8f279a64 scope link metric 1000
192.168.8.0/24 dev enx0c5b8f279a64 proto kernel scope link src 192.168.8.100 metric 100
linkdown
答案1
我完全同意 dirk 的评论:使用网络命名空间可以让路由更简单,没有特殊情况。但我希望这里有一个与通常不同的答案,它需要 Linux 内核 >= 4.10。
关于失败的尝试:POSTROUTING
顾名思义,已完成后路由决策已完成。这条链永远不会改变路线。应该用来做什么当地发起的流量是mangle/OUTPUT
(在 nftables 上是特殊type route hook output
链)。然后,它仍然需要通过使用标记与路由堆栈进行交互并纠正极端情况,也可能通过使用CONNMARK
而不仅仅是MARK
.要让它正常工作仍然很困难。
无论如何,这里有一个方法不是依赖于2016年出现的iptables
网络路由堆栈的功能uidrange
内核4.10:
添加对每个 UID 路由的支持。它允许管理员配置规则,例如:
# ip rule add uidrange 100-200 lookup 123
。自 5.0 起,所有 Android 设备都在使用此功能。它主要用于实施每个应用程序的路由策略(在 Android 上,每个应用程序都有自己的 UID)无需在 iptables 中重新路由数据包,这会破坏 getsockname() 和 MTU/MSS 计算,并且通常会破坏端到端连接犯罪, 犯罪,犯罪
由于路由堆栈将立即选择正确的路由,从而选择匹配的源 IP,因此不需要SNAT
此 IP。仍然需要一个小的“不干净”部分:它需要使用反向路径过滤器松动于屯设备,因为虽然目标用户获得与其他用户不同的路由表,但从该接口返回的返回流量不属于任何用户,因此不会使用该路由表。
在这个例子中用户1的 UID 将为 1234,并且任意选择的表 1001234 用于备用路由。
将相关主路由复制/更改到表1001234并放宽路由。每次重新建立隧道时都必须重新添加这些路由和设置,因为当接口消失和/或关闭时,路由和设置会丢失:
ip route add table 1001234 10.0.0.0/24 dev tun1 src 10.0.0.1
ip route add table 1001234 default dev tun1 #no need of a gateway on a layer 3 interface
sysctl -w net.ipv4.conf.tun1.rp_filter=2
这只需要一次,然后将立即影响用户:
ip rule add uidrange 1234-1234 lookup 1001234
不要添加任何iptables
nat 规则。当然仍然需要足够的防火墙规则。请注意,如果用户查询本地服务(例如:127.0.0.1:53 上可用的本地 DNS 缓存守护进程),守护进程发出的查询将不会使用隧道,因为守护进程具有不同的 uid。