更新:解决方案:我应该使用 OUTPUT 链,而不是 PREROUTING 链。此示例仍然不起作用,但我很快就会更新它。
在我看来这应该可以工作。我将所有路由规则从主表移至表 4,然后标记并将发往端口 80/443 的数据包定向至表 4。我期望端口 80 能够正常工作,就像我什么都没做但 gethostbyname 失败了一样?
#!/bin/bash -x
#
# Reset/Flush iptables
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
# Reset/Flush table 4
ip route flush table 4
# move all routing rules from the main table to table 4
ip route show table main | grep -v linkdown |
while read ROUTE
do
ip route add table 4 $ROUTE
ip route del table main $ROUTE
done
# MARK all HTTP(S) destination packets with a 4
iptables -t mangle -A PREROUTING -p tcp --dport 80 -j MARK --set-mark 4
iptables -t mangle -A PREROUTING -p tcp --dport 443 -j MARK --set-mark 4
iptables -t mangle -A PREROUTING -p udp --dport 53 -j MARK --set-mark 4
# packets marked as 4 find their routes via table 4
ip rule add fwmark 4 table 4
ip route flush cache
答案1
iptables(和/或 netfilter)具有各种钩子在路由堆栈中。当数据包通过路由堆栈中的某个步骤时,如果那里有一个 iptables 钩子,iptables 的钩子就会运行。当然,如果数据包没有到达这样的步骤,就不会运行 iptables 钩子。如果没有“到主机的路由”,路由堆栈会提前放弃,不会到达这些步骤。这就是在您的示例中删除(主表的)路由并留下一个依赖于 iptables 的路由表后发生的情况。这是一个先有鸡还是先有蛋的问题,但不需要一直这样做。您只需要一条路由,任何路由,这样您的规则就会触发并更改此路由。
我运行了你的脚本,并得到了我的设置:
# ip route
(nothing)
# ip route show table 4
default via 10.0.3.1 dev eth0
10.0.3.0/24 dev eth0 proto kernel scope link src 10.0.3.66
添加了OUTPUT规则:
iptables -t mangle -A OUTPUT -p udp -m udp --dport 53 -j MARK --set-xmark 0x4/0xffffffff
iptables -t mangle -A OUTPUT -p tcp -m tcp --dport 53 -j MARK --set-xmark 0x4/0xffffffff
iptables -t mangle -A OUTPUT -p tcp -m tcp --dport 443 -j MARK --set-xmark 0x4/0xffffffff
iptables -t mangle -A OUTPUT -p tcp -m tcp --dport 80 -j MARK --set-xmark 0x4/0xffffffff
什么都不起作用。
添加了 LAN 路由和不存在的虚假错误网关 10.0.3.9:
# ip route
default via 10.0.3.9 dev eth0
10.0.3.0/24 dev eth0 scope link
# ip neigh flush dev eth0
# ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
^C
--- 8.8.8.8 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1006ms
# ip neigh
10.0.3.9 dev eth0 FAILED
# ip neigh del 10.0.3.9 dev eth0
# dig +short @8.8.8.8 google.com.
172.217.22.142
# ip neigh
10.0.3.1 dev eth0 lladdr fe:d6:50:75:27:c9 REACHABLE
请注意现在使用了表 4 中的路由。但首先需要一条有效的路由(即使实际上不起作用,也要“在纸面上”),否则路由决策本身就会阻止使用 OUTPUT 规则。您可以使用查看iptables-save -c
计数器来查看它。