我正在尝试设置一个 OpenVPN VPN,它将通过 OpenVPN 服务器将部分(但不是全部)流量从客户端传输到互联网。
我的 OpenVPN 服务器在 eth0 上有一个公共 IP,并使用 tap0 创建本地网络 192.168.2.x。我有一个客户端从本地 IP 192.168.1.101 连接并获取 VPN IP 192.168.2.3。
在服务器上,我运行了:
iptables -A INPUT -i tap+ -j ACCEPT
iptables -A FORWARD -i tap+ -j ACCEPT
iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -o eth0 -j MASQUERADE
在客户端上,默认路由仍通过 192.168.1.1。为了将其指向 192.168.2.1 以进行 HTTP,我运行了
ip rule add fwmark 0x50 table 200
ip route add table 200 default via 192.168.2.1
iptables -t mangle -A OUTPUT -j MARK -p tcp --dport 80 --set-mark 80
现在,如果我尝试在客户端上访问一个网站(例如,wget google.com),它就会挂在那里。在服务器上,我可以看到
$ sudo tcpdump -n -i tap0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tap0, link-type EN10MB (Ethernet), capture size 96 bytes
05:39:07.928358 IP 192.168.1.101.34941 > 74.125.67.100.80: S 4254520618:4254520618(0) win 5840 <mss 1334,sackOK,timestamp 558838 0,nop,wscale 5>
05:39:10.751921 IP 192.168.1.101.34941 > 74.125.67.100.80: S 4254520618:4254520618(0) win 5840 <mss 1334,sackOK,timestamp 559588 0,nop,wscale 5>
其中 74.125.67.100 是 google.com 获取的 IP。
为什么 MASQUERADE 不起作用?更准确地说,我看到源显示为 192.168.1.101 —— 难道不应该有什么东西表明它来自 VPN 吗?
编辑:一些路线[来自客户端]
$ ip route show table main
192.168.2.0/24 dev tap0 proto kernel scope link src 192.168.2.4
192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.101 metric 2
169.254.0.0/16 dev wlan0 scope link metric 1000
default via 192.168.1.1 dev wlan0 proto static
$ ip route show table 200
default via 192.168.2.1 dev tap0
答案1
你能发布输出吗ip 路由显示表主要和ip 路由显示表 200?我怀疑您的“200”表中缺少几条路线。您的“200”路线表应该与“主”表的路线基本相同,唯一的区别是默认路线。
我看到您已更新,我相信我最初的建议是正确的。请注意,您的主表包含本地网络和 VPN 链接的“范围链接”路由?这些路由也必须添加到“200”表中。
除了您使用的其他命令之外,请尝试运行这些命令。
ip route add 192.168.2.0/24 dev tap0 proto kernel scope link src 192.168.2.4 table 200
ip route add 192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.101 metric 2 table 200
ip route flush cache
如果您想要编写这些路线的创建脚本,您可以使用它。它将把所有“范围链接”路线从主路线表复制到您的其他表中。
#!/bin/bash
IFACE=wlan0
RT=200
/sbin/ip route list scope link table main proto kernel dev ${IFACE} \
| while read ROUTE ; do
# and add that route to all the tables mentioned in the rrtables option
# in the interfaces file
/sbin/ip route add table ${RT} scope link proto kernel dev ${IFACE} ${ROUTE}
done
又有更新了。我刚刚注意到我之前错过了一些相当明显的东西。
您的 MASQ 语句似乎在 eth0 上起作用。从您发布的路由表来看,您的输出设备不是 eth0。而是这个。
iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -o eth0 -j MASQUERADE
您可能应该只使用这样的语句。
iptables -t nat -A POSTROUTING -o tap0 -j MASQUERADE
答案2
在服务器上尝试:
echo 1 > /proc/sys/net/ipv4/ip_forward
我认为这样可以暂时启用它。如果有效,请添加:
net.ipv4.conf.default.forwarding=1
到您的 /etc/sysctl.conf 以使其永久生效。
答案3
有两件事是错误的:
首先,在客户端,我需要将源通过 SNAT 转换为实际 IP。
其次,反向路径过滤器阻止了返回的数据包,因为它认为它们是伪造的。echo 0 > /proc/sys/net/ipv4/conf/tun0/rp_filter
已修复此问题