我有一个 Linux 机器,它是一个 OpenVPN 客户端,它的所有流量都通过 Tunel,我有一个 Nginx 服务器,我想让它通过 eth0,我试图做的是通过 192.168.1.1 将端口 80 上的所有流量重新路由到 eth0
root@digger02:~# ip route
0.0.0.0/1 via 10.8.0.1 dev tun0
default via 192.168.1.1 dev eth0 proto dhcp src 192.168.1.154 metric 10
10.8.0.0/24 dev tun0 proto kernel scope link src 10.8.0.2
XXX.XXX.XXX.XXX via 192.168.1.1 dev eth0
128.0.0.0/1 via 10.8.0.1 dev tun0
192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.154
192.168.1.1 dev eth0 proto dhcp scope link src 192.168.1.154 metric 10
其中 XXX.XXX.XXX.XXX 是我的 VPN 服务器的公共 IP 地址
root@digger02:~# iptables -t mangle -L -v -n
Chain PREROUTING (policy ACCEPT 665K packets, 164M bytes)
pkts bytes target prot opt in out source destination
176 8430 MARK tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 MARK set 0x80
Chain INPUT (policy ACCEPT 665K packets, 164M 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 715K packets, 91M bytes)
pkts bytes target prot opt in out source destination
35 82961 MARK all -- * * 0.0.0.0/0 0.0.0.0/0 cgroup 1114129 MARK set 0xb
Chain POSTROUTING (policy ACCEPT 715K packets, 91M bytes)
pkts bytes target prot opt in out source destination
root@digger02:~# cat /etc/iproute2/rt_tables
#
# reserved values
#
255 local
254 main
253 default
0 unspec
#
# local
#
#1 inr.ruhep
80 http
11 novpn
这就是我尝试做的
iptables -t mangle -A PREROUTING -p tcp --dport 80 -j MARK --set-mark 0x80
echo "80 http" >> /etc/iproute2/rt_tables
ip route add default via 192.168.1.1 dev eth0 table http
ip rule add fwmark 0x80 lookup 80
ip route flush table 100
ip route flush cache
ip rule add from xxx.xxx.xxx.xxx table 100
ip route add table 100 to 192.168.1.0/24 dev eth0
ip route add table 100 default via 192.168.1.1
其中表 100 是由 OpenVPN 的路由脚本创建的,xxx.xxx.xxx.xxx 是我的公网 IP
对我来说没什么用,我甚至试过这个脚本https://gist.github.com/kriswebdev/a8d291936fe4299fb17d3744497b1170 它基本上标记了应用程序的所有流量
我觉得 iptables 可能根本无法在我的系统上运行,我该如何诊断
答案1
自从Linux 内核 4.17,无需使用iptables根本没有:路由堆栈可以直接根据端口选择不同的路由,而无需标记、重新路由和需要 NAT 创可贴(但通常仅适用于 UDP 或作为客户端的 TCP,而不是像这里一样适用于作为服务器的 TCP):
在 VPN 客户端上运行 nginx 服务器的情况下,假设没有iptables规则集,并且尚未设置附加路由规则...
在路由表中添加备用路由,前面是 LAN 路由(它至少可以防止来自 LAN 的连接无用地通过路由器,路由器必须发出 ICMP 重定向)。如果接口关闭然后打开,此表将被刷新,因此这应该与管理接口的工具集成:
ip route add 192.168.1.0/24 dev eth0 table 80
ip route add default via 192.168.1.1 dev eth0 table 80
选择本地发起的(这是这里的特殊角色iif lo
)从端口 80(到任何地方)的回复流量来使用此表:
ip rule add iif lo ipproto tcp sport 80 lookup 80
对于传入的 HTTP 流量,即原始方向,也同样如此(实际上不需要,因为安全防御框架协议将不会被启用,但为了保持一致性):
ip rule add iif eth0 ipproto tcp dport 80 lookup 80
松开安全防御框架协议万一已启用因为我不确定 TCP 相关流量(例如 ICMP 错误)局部性尿道畸变如果设置为严格,可能会被接受:
sysctl -w net.ipv4.conf.eth0.rp_filter=2
HTTP/3 支持(使用 QUIC,因此结束UDP)只需要对 UDP 遵循相同的规则:
ip rule add iif lo ipproto udp sport 80 lookup 80
ip rule add iif eth0 ipproto udp dport 80 lookup 80
如果某些 IP 地址在端口 80 上属于此例外,则一种方法是使用以下方法将它们添加到路由表中:扔关键字,从而落入主路由表。例如,要使来自 10.8.0.0/24 的流量保证是 OpenVPN 流量,仍可与 nginx 配合使用:
throw
- 与政策规则一起使用的特殊控制路线。如果选择了这样的路线,则终止此表中的查找,假装没有找到路线。没有策略路由,就相当于路由表中没有路由。数据包被丢弃,并生成 ICMP 消息网络不可达。本地发送者会收到 ENETUNREACH 错误。
ip route add throw 10.8.0.0/24 table 80