用于标记路由表流量的 IPTable mangle 规则

用于标记路由表流量的 IPTable mangle 规则

我正在尝试使用 Ubuntu Server 16.04 设置 VPN 路由器。

我将路由器配置为安全的,这样流量就不会泄漏,或者如果 VPN 出现故障,它将无法关闭。

路由器有一个无线接口 (wlp2s0),可连接到我的无线网络以实现互联网连接,还有一个以太网接口 (enp1s0),我可以将笔记本电脑插入其中。

理想情况下,openvpn 将在启动时运行并使用 wlp2s0 创建 tun0 接口,然后一些 iptable 规则将 enp1s0 流量转发到 tun0。

为了实现防止流量泄漏的目标,我制作了一个启动脚本来刷新所有路由,然后将 wlp2s0 的本地子网路由添加到 MAIN 表中。它还为表 100 添加一条默认路由 wlp2s0。

我添加了一条 iptables mangle 规则来标记 openvpn 流量,然后添加了一条 fw 规则,使标记的流量使用表 100。

所以基本上,我只希望 openvpn 流量能够使用无线默认路由(表 100),以便它可以创建隧道。所有其他流量将是本地流量或通过隧道。

我的启动脚本工作正常,它在启动时创建正确的路由。我的 iptable 规则和 fw 规则似乎也是正确的。

问题是 openvpn 流量似乎不符合 iptables mangle 规则。

标记 openvpn 流量的 iptable 规则。

iptables -t mangle -A OUTPUT -p tcp --dport 501 -j MARK --set-mark 2

启动脚本。

ip route add table 100 default via 192.168.0.1 dev wlp2s0
ip rule add fwmark 0x2 table 100
ip route flush table main
ip route add 192.168.0.0/24 dev wlp2s0

大多数人会要求的各种命令的输出

administrator@ubuntu-svr:~$ sudo iptables -t mangle -L -v
Chain PREROUTING (policy ACCEPT 6153 packets, 1859K bytes)
 pkts bytes target     prot opt in     out     source               destination                  

Chain INPUT (policy ACCEPT 1961 packets, 297K bytes)
 pkts bytes target     prot opt in     out     source               destination       

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination        

Chain OUTPUT (policy ACCEPT 1348 packets, 128K bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 MARK       tcp  --  any    any     anywhere             anywhere             tcp dpt:501 MARK set 0x2                  

Chain POSTROUTING (policy ACCEPT 1348 packets, 128K bytes)
 pkts bytes target     prot opt in     out     source               destination         

administrator@ubuntu-svr:~$ ip rule
0:  from all lookup local 
32765:  from all fwmark 0x2 lookup 100 
32766:  from all lookup main 
32767:  from all lookup default 

administrator@ubuntu-svr:~$ ip route show table main
192.168.0.0/24 dev wlp2s0  scope link 

administrator@ubuntu-svr:~$ ip route show table 100
default via 192.168.0.1 dev wlp2s0 

administrator@ubuntu-svr:~$ ip route get 8.8.8.8 mark 0x2
8.8.8.8 via 192.168.0.1 dev wlp2s0  src 192.168.0.209  mark 2

因此,从上面的输出中您可以看到正确的路由、iptable mangle 规则和 fw 规则都已就位。

当我发出“ip route get”get 命令时,您可以看到为标记的流量选择了正确的路由。

然而,iptables mangle 规则并没有受到影响。我发出“telnet 8.8.8.8 501”,但规则仍然没有命中!即使流量是本地生成的并达到 tcp 501,这应该与规则匹配。

openvpn 流量是由路由器本身生成的。根据 iptables 的手册页,mangle 的 OUTPUT 链用于修改本地生成的流量 PREROUTE 决策。

我在这里完全不知所措。我读过其他人有类似问题的帖子,但似乎找不到解决方案。

答案1

问题是表中缺少默认路由main。检查时无法检测到这一点,ip route get ... mark ...因为直接递上的“解决方案”使整个路径短路。

由于没有默认路由,因此在数据包有机会到达 mangle OUTPUT 链之前,对 8.8.8.8 的路由查找会失败,并显示“网络无法访问”:

添加任何表中的默认路由main(即使使用不存在的路由器,只要它是有效的语法)将允许预期的流:

  • 数据包生成,
  • 第一次在表中检查路线ip rule,认为存在,
  • 遍历mangle OUTPUT链,继承标记,
  • 重新路由(重新路由签入Netfilter 和通用网络中的数据包流),从而第二次触发表中的查找ip rule
  • 获取表 100 上的早期查找并获得其最终路线“ via 192.168.0.1 dev wlp2s0”。

因此,在 LAN 中选择一个 IP不属于任何主机,假设 192.168.0.250 并将其添加到脚本中,从而给出:

ip route add table 100 default via 192.168.0.1 dev wlp2s0
ip rule add fwmark 0x2 table 100
ip route flush table main
ip route add 192.168.0.0/24 dev wlp2s0
ip route add default via 192.168.0.250 dev wlp2s0

将解决问题中所做的测试:

  • 任何未与目标 tcp 端口 501 建立的连接都会触发对 192.168.0.250 的 ARP 请求,该请求应在 3 秒后超时,并显示消息“没有到主机的路由”(而不是“网络无法访问”)
  • 与目标 tcp 端口 501 建立的任何连接都将(解析 ARP 请求并)通过 192.168.0.1

相关内容