Debian系统下OpenVPN客户端后端的Nginx反向代理流量路由配置问题
嘿,我之前也碰到过几乎一模一样的场景,咱们一步步来排查和解决这个问题:
核心问题其实是:当请求打到OpenVPN分配的公网IP x.x.x.x 时,系统大概率把这个流量顺着VPN链路又发回去了,完全没给到本地的Nginx。咱们从这几个关键方向入手:
1. 确保Nginx监听所有可用网卡(包括OpenVPN虚拟网卡)
你当前的Nginx配置里listen 80; listen [::]:80;理论上是监听所有网卡的80端口,但为了稳妥,咱们直接明确指定监听所有地址,避免虚拟网卡被遗漏:
server { listen 0.0.0.0:80; # 监听所有IPv4地址的80端口 listen [::]:80; # 监听所有IPv6地址的80端口 proxy_buffering on; proxy_buffer_size 128k; proxy_buffers 4 256k; location / { proxy_pass http://localhost:9000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 你原来的其他配置可以保留在这里 } }
修改后重启Nginx生效:sudo systemctl restart nginx
2. 添加静态路由,让VPN公网IP的流量留在本地
OpenVPN连接后通常会生成默认路由,把大部分流量导向VPN链路,但请求x.x.x.x的流量如果也走VPN,就会形成环路。咱们加一条静态路由,告诉系统:访问这个公网IP直接走本地物理网卡。
先通过ip addr查看你的本地物理网卡名(比如eth0、enp0s3),然后执行:
# 替换成你的本地物理网卡名和VPN公网IP sudo ip route add x.x.x.x/32 dev eth0
如果要让这个路由重启后依然生效,把这条命令加到/etc/rc.local里(Debian 10及以后可能需要先创建这个文件并赋予执行权限),或者写进OpenVPN的up脚本里自动触发。
3. 配置iptables,允许OpenVPN虚拟网卡的流量访问Nginx
有时候防火墙会拦截来自VPN虚拟网卡(一般是tun0或tap0)的流量,咱们需要手动放行:
sudo iptables -A INPUT -i tun0 -p tcp --dport 80 -j ACCEPT
如果要持久化这个规则,先安装iptables-persistent包:sudo apt install iptables-persistent,然后执行iptables-save > /etc/iptables/rules.v4保存规则。
4. 调整OpenVPN配置,避免强制路由覆盖本地规则
打开你的OpenVPN客户端配置文件(一般在/etc/openvpn/client.conf),如果里面有redirect-gateway def1这类强制所有流量走VPN的配置,一定要加上本地路由豁免:
# 替换成你的VPN公网IP和本地局域网网段 route x.x.x.x 255.255.255.255 net_gateway route 192.168.1.0 255.255.255.0 net_gateway
这段配置的意思是:访问VPN公网IPx.x.x.x和本地局域网的流量,都走物理网卡的默认网关,不经过VPN链路。
最后验证步骤
- 重启OpenVPN客户端:
sudo systemctl restart openvpn@client - 再次重启Nginx:
sudo systemctl restart nginx - 从外部机器访问
http://x.x.x.x或http://sentry.mycompany.com,测试是否能正常转发到localhost:9000 - 也可以在本地用
curl -H "Host: sentry.mycompany.com" http://x.x.x.x快速验证
按这个流程走下来,应该就能解决流量路由的问题了!
备注:内容来源于stack exchange,提问作者Martin Claesson

