我想使用Linux 本地网关上的基于端口的路由。这是我的网络图:
192.168.42.148/24 192.168.42.1/24 192.168.44.2 192.168.44.1
+--------------------+ +----------------------------+ +----------+
| Workstation (eth0)-|----------------|-(em0) Local_GW (tun0)-|------------| VPN_GW |
+--------------------+ | (rl0) | +----------+
+-------------|--------------+
10.133.8.79/21 |
|
10.133.15.254/21 |
+--------------------+
| Provider_GW |
+--------------------+
Provider_GW 仅允许 21,110,143,554,587,993,995,5222,6666:6669 作为发往互联网的数据包的传出端口。Local_GW 通过 UDP SSL VPN(OpenVPN)连接到 VPN_GW
因此,我想使用:
- 10.133.15.254 作为 TCP 数据包的网关,其传出端口在列表 21,110,143,554,587,993,995,5222,6666:6669 中
- 192.168.44.1 作为 TCP 数据包的网关,具有任何其他传出端口
以下是我遵循的步骤:
#!/bin/bash
## Flush FIP (Forbidden Internet Ports) table
ip route flush table FIP
## Copy all routes from main table except the default one
ip route show table main | grep -Ev ^default | while read ROUTE ; do ip route add table FIP $ROUTE; done
## Add default route
ip route add default via 192.168.44.1 table FIP
## Flush iptables PREROUTING chain in table mangle
iptables -t mangle -F PREROUTING
## Create iptables rules for packet marking
iptables -t mangle -N MFIP
### Only mark packets bound for the Internet
iptables -t mangle -A MFIP --dst 192.168.0.0/16 --jump RETURN
iptables -t mangle -A MFIP --dst 172.16.0.0/12 --jump RETURN
iptables -t mangle -A MFIP --dst 10.0.0.0/8 --jump RETURN
iptables -t mangle -A MFIP --dst 169.254.0.0/16 --jump RETURN
iptables -t mangle -A MFIP --jump MARK --set-mark 1
iptables -t mangle -A PREROUTING -i em0 -p tcp -m multiport ! --dports 21,110,143,554,587,993,995,5222,6666:6669 --jump MFIP
## Delete old routing rule if it exist
ip rule del fwmark 1
## Create new routing rule
ip rule add fwmark 1 table FIP
## Zero Counters (useful for debugging)
iptables -t mangle -Z
我无法从工作站:
fabien@Workstation:~$ ssh [email protected]
ssh: connect to host sdf.org port 22: Connection timed out
但是我可以看到数据包已按预期进行标记和路由:
(在 Local_GW 上):
fabien@Local_GW:~$ sudo tcpdump -fi em0 tcp port 22 and host not 192.168.42.1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on em0, link-type EN10MB (Ethernet), capture size 65535 bytes
13:07:32.065071 IP LoopbackMarvin.local.52540 > 192.94.73.15.ssh: Flags [S], seq 3448990172 [...]
13:07:35.064024 IP LoopbackMarvin.local.52540 > 192.94.73.15.ssh: Flags [S], seq 3448990172 [...]
13:07:41.060423 IP LoopbackMarvin.local.52540 > 192.94.73.15.ssh: Flags [S], seq 3448990172 [...]
Local_GW 确实收到了来自工作站的 SYN 数据包
fabien@Local_GW:~$ sudo iptables -t mangle -vL -n
Chain PREROUTING (policy ACCEPT 7046 packets, 829K bytes)
pkts bytes target prot opt in out source destination
558 43499 MFIP tcp -- em0 * 0.0.0.0/0 0.0.0.0/0 multiport dports ! 21,110,143,554,587,993,995,5222,6666:6669
Chain INPUT (policy ACCEPT 5690 packets, 713K bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 220 packets, 49131 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 540 packets, 352K bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 767 packets, 402K bytes)
pkts bytes target prot opt in out source destination
Chain MFIP (1 references)
pkts bytes target prot opt in out source destination
555 43319 RETURN all -- * * 0.0.0.0/0 192.168.0.0/16
0 0 RETURN all -- * * 0.0.0.0/0 172.16.0.0/12
0 0 RETURN all -- * * 0.0.0.0/0 10.0.0.0/8
0 0 RETURN all -- * * 0.0.0.0/0 169.254.0.0/16
3 180 MARK all -- * * 0.0.0.0/0 0.0.0.0/0 MARK xset 0x1/0xffffffff
显然,来自 Workstation 的 SYN 数据包已被 iptables 正确标记。
fabien@Local_GW:~$ sudo tcpdump -fi tun0 tcp port 22
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tun0, link-type RAW (Raw IP), capture size 65535 bytes
13:07:32.065153 IP 192.168.42.148.52540 > 192.94.73.15.ssh: Flags [S], seq 3448990172 [...]
13:07:32.487217 IP 192.94.73.15.ssh > 192.168.42.148.52540: Flags [S.], seq 2834611855 [...]
13:07:35.064062 IP 192.168.42.148.52540 > 192.94.73.15.ssh: Flags [S], seq 3448990172 [...]
13:07:35.341717 IP 192.94.73.15.ssh > 192.168.42.148.52540: Flags [S.], seq 2834611855 [...]
13:07:35.510967 IP 192.94.73.15.ssh > 192.168.42.148.52540: Flags [S.], seq 2834611855 [...]
13:07:41.060459 IP 192.168.42.148.52540 > 192.94.73.15.ssh: Flags [S], seq 3448990172 [...]
13:07:41.336589 IP 192.94.73.15.ssh > 192.168.42.148.52540: Flags [S.], seq 2834611855 [...]
13:07:41.411675 IP 192.94.73.15.ssh > 192.168.42.148.52540: Flags [S.], seq 2834611855 [...]
13:07:53.411081 IP 192.94.73.15.ssh > 192.168.42.148.52540: Flags [S.], seq 2834611855 [...]
来自 Workstation 的 SYN 数据包被正确路由到 VPN_GW,它甚至接收并应答(来自 sdf.org ssh 服务器)192.94.73.15.ssh > 192.168.42.148.52540: Flags [S.], seq 2834611855
:。但是,Local_GW 不会将此响应数据包路由回 Workstation,为什么?我肯定忽略了一些显而易见的东西但我不明白是什么。
非常感谢您的阅读。
如果您需要有关我的配置的确切详细信息,以下是来自 iptables 和 ip 的(非常)详细的输出。抱歉,如果我的问题太长了,我会尽量做到尽可能精确。
防火墙:
fabien@Local_GW:~$ sudo iptables -t nat -vL -n
Chain PREROUTING (policy ACCEPT 145K packets, 10M bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 1934 packets, 137K bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 1938 packets, 137K bytes)
pkts bytes target prot opt in out source destination
0 0 MASQUERADE all -- * rl0 192.168.44.0/24 0.0.0.0/0
668 43570 MASQUERADE all -- * rl0 192.168.42.0/24 0.0.0.0/0
fabien@Local_GW:~$ sudo iptables -vL -n
Chain INPUT (policy ACCEPT 132K packets, 15M bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 34345 packets, 24M bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 15490 packets, 7741K bytes)
pkts bytes target prot opt in out source destination
路由表:
fabien@Local_GW:~$ sudo ip route show
192.168.46.1 dev tun1 proto kernel scope link src 192.168.46.3
192.168.44.1 dev tun0 proto kernel scope link src 192.168.44.2
192.168.46.0/24 via 192.168.46.1 dev tun1
192.168.42.0/24 dev em0 proto kernel scope link src 192.168.42.1
192.168.43.0/24 via 192.168.44.1 dev tun0
10.133.8.0/21 dev rl0 proto kernel scope link src 10.133.8.79
169.254.0.0/16 dev em0 scope link metric 1000
default via 10.133.15.254 dev rl0 metric 100
fabien@Local_GW:~$ sudo ip route show table FIP
192.168.44.1 dev tun0 proto kernel scope link src 192.168.44.2
192.168.46.1 dev tun1 proto kernel scope link src 192.168.46.3
192.168.46.0/24 via 192.168.46.1 dev tun1
192.168.42.0/24 dev em0 proto kernel scope link src 192.168.42.1
192.168.43.0/24 via 192.168.44.1 dev tun0
10.133.8.0/21 dev rl0 proto kernel scope link src 10.133.8.79
169.254.0.0/16 dev em0 scope link metric 1000
default via 192.168.44.1 dev tun0
fabien@Zaphod:~$ ip rule show
0: from all lookup local
32765: from all fwmark 0x1 lookup FIP
32766: from all lookup main
32767: from all lookup default
答案1
禁用反向路径过滤器可以解决此问题。
root@Local_GW:/# echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter
但是我不明白为什么这是必要的。有人能提供有关此问题的更多详细信息吗?192.168.44.1 在表 FIP 中设置为默认路由,内核应该知道来自互联网的数据包可能会通过 tun0。
另一方面,禁用反向路径过滤器是否会产生安全漏洞?