如何通过SSH隧道将OpenVPN服务器的全部客户端流量转发至另一服务器
先看了你的OpenVPN配置,push "redirect-gateway def1 bypass-dhcp"这条已经设置到位,客户端的所有流量都会路由到Server A上。接下来我会一步步带你把这些流量通过SSH隧道转发到Server B,最终从Server B的公网IP出去。
先明确整个流量路径:
- OpenVPN客户端 → Server A的OpenVPN tun接口 → Server A与Server B之间的SSH虚拟隧道 → Server B → 公网
第一步:在Server B上开启IP转发
Server B需要具备转发流量的能力,先开启内核IP转发:
- 临时生效(重启后失效):
echo 1 > /proc/sys/net/ipv4/ip_forward
- 永久生效:编辑
/etc/sysctl.conf,找到net.ipv4.ip_forward一行,修改为:
net.ipv4.ip_forward = 1
执行sysctl -p让配置立即生效。
第二步:在Server B上配置iptables做SNAT
为了让OpenVPN客户端的流量能通过Server B的公网IP访问互联网,需要配置源地址转换:
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
⚠️ 注意:把eth0替换成Server B的公网网卡名称,可以用ip addr命令查看。
如果要永久保存iptables规则,Ubuntu系统可以安装iptables-persistent包,然后执行iptables-save > /etc/iptables/rules.v4。
第三步:在Server A与Server B之间建立SSH虚拟隧道
我们用SSH的-w选项创建一对点对点虚拟网卡,这种方式比端口转发更稳定,类似小型VPN:
- 在Server A上以root身份执行(需要Server B的root权限):
ssh -f -N -w 0:0 root@w.x.y.z
参数解释:
-f:后台运行SSH进程-N:仅建立隧道,不执行远程命令-w 0:0:在Server A创建tun0网卡,Server B同步创建tun0网卡,作为点对点连接
- 配置虚拟网卡IP:
- 在Server A上执行:
ip addr add 192.168.100.1/30 dev tun0 ip link set tun0 up - 在Server B上执行:
ip addr add 192.168.100.2/30 dev tun0 ip link set tun0 up
ping 192.168.100.2,能通就说明隧道建立成功。 - 在Server A上执行:
第四步:在Server A上配置路由规则,引导流量走隧道
我们需要让来自OpenVPN客户端(10.8.0.0/24)的流量单独走SSH隧道,不影响Server A自身的网络:
# 创建单独的路由表(编号100) echo "100 ssh-tunnel" >> /etc/iproute2/rt_tables # 添加默认路由到Server B的虚拟网卡IP ip route add 0.0.0.0/0 via 192.168.100.2 dev tun0 table 100 # 添加规则:来自10.8.0.0/24的流量使用路由表100 ip rule add from 10.8.0.0/24 table 100
第五步:调整Server A的iptables规则
你原来的MASQUERADE规则是让客户端流量从Server A的公网网卡出去,现在需要删除这条规则:
iptables -t nat -D POSTROUTING -s 10.8.0.0/24 -j MASQUERADE
如果原来的规则指定了网卡(比如-o eth0),记得加上对应的参数删除。
第六步:设置SSH隧道开机自启
手动建立的隧道重启后会消失,我们把它做成systemd服务:
在Server A上创建/etc/systemd/system/ssh-tunnel.service文件,内容如下:
[Unit] Description=SSH Tunnel to Server B for OpenVPN Traffic After=network.target openvpn-server@server.service [Service] Type=forking User=root ExecStart=/usr/bin/ssh -f -N -w 0:0 root@w.x.y.z ExecStartPost=/usr/bin/ip addr add 192.168.100.1/30 dev tun0 ExecStartPost=/usr/bin/ip link set tun0 up ExecStartPost=/usr/bin/ip route add 0.0.0.0/0 via 192.168.100.2 dev tun0 table 100 ExecStartPost=/usr/bin/ip rule add from 10.8.0.0/24 table 100 ExecStop=/usr/bin/pkill -f "ssh -f -N -w 0:0 root@w.x.y.z" ExecStopPost=/usr/bin/ip link set tun0 down ExecStopPost=/usr/bin/ip addr del 192.168.100.1/30 dev tun0 ExecStopPost=/usr/bin/ip rule del from 10.8.0.0/24 table 100 ExecStopPost=/usr/bin/ip route del 0.0.0.0/0 via 192.168.100.2 dev tun0 table 100 [Install] WantedBy=multi-user.target
然后启用并启动服务:
systemctl daemon-reload systemctl enable ssh-tunnel.service systemctl start ssh-tunnel.service
⚠️ 重要前提:确保Server A的root用户可以免密码SSH登录Server B,否则隧道无法自动建立。可以在Server A上执行ssh-copy-id root@w.x.y.z,把Server A的root公钥复制到Server B的~/.ssh/authorized_keys中。
测试配置
连接你的OpenVPN客户端,访问https://ifconfig.me,如果显示Server B的公网IP(w.x.y.z),说明整个转发流程正常工作了。
如果遇到问题,可以从以下几点排查:
- Server B的
net.ipv4.ip_forward是否为1(cat /proc/sys/net/ipv4/ip_forward) - SSH隧道状态:Server A上执行
ip link show tun0,看是否处于UP状态 - 路由规则:执行
ip rule list和ip route show table 100,确认规则已生效 - iptables规则:Server B上执行
iptables -t nat -L POSTROUTING -v,看是否有匹配的流量
备注:内容来源于stack exchange,提问作者Pejman Ghasemi




