通过特定接口 (tum1) 路由用户流量

通过特定接口 (tum1) 路由用户流量

问题:如何为特定用户通过 tun1 路由流量?

到目前为止我已经尝试过:我遵循了:

1:iptables 将所有流量转发到接口

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

不要添加任何iptablesnat 规则。当然仍然需要足够的防火墙规则。请注意,如果用户查询本地服务(例如:127.0.0.1:53 上可用的本地 DNS 缓存守护进程),守护进程发出的查询将不会使用隧道,因为守护进程具有不同的 uid。

相关内容