【运维实战】内网服务器无法联网?巧用 SSH 隧道实现反向代理访问公网资源 (Docker/PortForwarding)
📚 前言
在企业运维和开发场景中,我们经常遇到这样的网络架构:
- 服务器环境 :出于安全考虑,服务器位于隔离内网,没有配置公网出口 IP,无法访问互联网。
- 开发环境:运维人员的本地电脑(PC/Mac)可以通过 VPN 或堡垒机 SSH 连接到该服务器,且本地电脑拥有正常的互联网访问权限。
- 痛点 :服务器需要安装依赖(如
yum install,docker pull,pip install),但由于没网,只能离线拷贝安装包,效率极低。
本文将介绍一种利用 SSH 协议自带的 Remote Port Forwarding (远程端口转发) 功能,搭建一条临时隧道,让内网服务器通过本地开发机的网络访问公网资源(如阿里云镜像源、Maven 中央仓库等)。
💡 技术原理:SSH 反向隧道
SSH 不仅可以用于远程登录,还内置了强大的隧道功能。其中 -R 参数用于创建反向隧道。
原理流程:
- 本地电脑开启一个流量转发服务(通常使用 HTTP 或 SOCKS 协议)。
- 通过 SSH 建立连接,将服务器的某个端口(如 8888)映射到本地电脑的转发端口。
- 服务器配置环境变量,将网络请求发送给自身的 8888 端口。
- SSH 进程将请求加密,通过隧道传输到本地电脑,再由本地电脑代为请求公网资源。
🛠️ 方案一:命令行快速通道 (SSH -R)
适用于临时维护、拉取代码或安装少量软件。
1. 前置准备
确保你的本地电脑上已经开启了一个代理服务/转发服务 。
(注:如果本地没有现成的服务,可以使用 Python 或简单的 SOCKS 服务开启一个端口,例如监听在 1080 或 7890 端口)。
2. 建立隧道
在本地电脑的终端执行以下命令:
bash
# 语法:ssh -R <服务器端口>:localhost:<本地服务端口> <用户名>@<服务器IP>
# 示例:将服务器的 8888 端口映射到本地的 7890 端口
ssh -o ServerAliveInterval=60 -R 8888:localhost:7890 root@192.168.1.100
-R 8888:localhost:7890:核心参数,意为让远程服务器监听 8888,流量转发至本地 7890。-o ServerAliveInterval=60:发送心跳包,防止连接因空闲断开。
3. 服务器端验证
登录到服务器,进行连通性测试:
bash
# 临时设置环境变量
export http_proxy=http://127.0.0.1:8888
export https_proxy=http://127.0.0.1:8888
# 测试访问公网(以百度或阿里云镜像为例)
curl -I https://www.baidu.com
如果返回 HTTP/1.1 200 OK,说明隧道已打通。
🐳 方案二:基于 Docker 的持久化方案 (推荐)
如果需要长期保持通道稳定,使用基于 autossh 的 Docker 容器是最佳实践,它支持断线自动重连。
1. 编写 docker-compose.yml
在本地电脑上创建文件:
yaml
version: '3'
services:
autossh-tunnel:
image: jnovack/autossh
container_name: ssh-reverse-tunnel
environment:
- SSH_REMOTE_USER=root # 服务器用户名
- SSH_REMOTE_HOST=192.168.1.100 # 服务器内网IP
- SSH_REMOTE_PORT=22 # SSH端口
# 🔥 核心配置:反向代理模式
- SSH_MODE=-R
- SSH_TUNNEL_PORT=8888 # 服务器端监听的端口
- SSH_TARGET_HOST=host.docker.internal # 指向本地宿主机
- SSH_TARGET_PORT=7890 # 本地网络出口服务的端口
volumes:
- ./id_rsa:/id_rsa:ro # 挂载私钥实现免密登录
# 允许容器访问宿主机网络
extra_hosts:
- "host.docker.internal:host-gateway"
restart: always
注意 :请将私钥文件
id_rsa放置在同级目录下。
2. 启动服务
bash
docker-compose up -d
容器启动后,会自动监控 SSH 连接状态,确保隧道全天候可用。
⚙️ 进阶:如何配置服务器软件走代理?
打通隧道后,需要配置服务器上的软件使用该代理端口。
1. 系统级配置 (APT/YUM/Curl)
编辑 /etc/profile 或用户目录下的 .bashrc:
bash
export http_proxy=http://127.0.0.1:8888
export https_proxy=http://127.0.0.1:8888
# 如果本地服务支持 SOCKS5 协议
export all_proxy=socks5://127.0.0.1:8888
执行 source /etc/profile 生效。
2. Docker Pull 加速
Docker 守护进程需要单独配置代理。创建或修改 /etc/systemd/system/docker.service.d/http-proxy.conf:
ini
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:8888"
Environment="HTTPS_PROXY=http://127.0.0.1:8888"
# 配置不走代理的地址(如私有仓库、K8s内部地址)
Environment="NO_PROXY=localhost,127.0.0.1,private-registry.internal"
重启 Docker 服务:
bash
systemctl daemon-reload
systemctl restart docker
🚧 常见问题排查
-
连接被拒绝 (Connection Refused):
- 检查本地电脑的端口(如 7890)是否开启。
- 检查本地电脑的防火墙设置,确保允许 Docker 容器或 SSH 进程访问该端口。
- 部分本地网络服务默认只监听
127.0.0.1,需开启"允许局域网连接"或监听0.0.0.0。
-
速度慢:
- 受限于 SSH 协议的加密解密开销以及本地电脑的上行带宽,该方案适合传输代码、配置文件或普通软件包,不建议传输超大文件。
🎉 总结
通过 SSH 反向隧道,我们无需在内网防火墙上开洞,利用现有的 SSH 通道即可巧妙解决内网服务器的公网资源访问问题。这对于隔离环境下的 DevOps 运维非常实用。
希望这篇文章能帮到你!如果有疑问,欢迎在评论区留言交流。
(本文归档于:服务器运维 / Linux技巧 / 网络配置)