✨【运维实战】内网服务器无法联网?巧用 SSH 隧道实现反向代理访问公网资源 (Docker/PortForwarding)

【运维实战】内网服务器无法联网?巧用 SSH 隧道实现反向代理访问公网资源 (Docker/PortForwarding)

📚 前言

在企业运维和开发场景中,我们经常遇到这样的网络架构:

  • 服务器环境 :出于安全考虑,服务器位于隔离内网,没有配置公网出口 IP,无法访问互联网。
  • 开发环境:运维人员的本地电脑(PC/Mac)可以通过 VPN 或堡垒机 SSH 连接到该服务器,且本地电脑拥有正常的互联网访问权限。
  • 痛点 :服务器需要安装依赖(如 yum install, docker pull, pip install),但由于没网,只能离线拷贝安装包,效率极低。

本文将介绍一种利用 SSH 协议自带的 Remote Port Forwarding (远程端口转发) 功能,搭建一条临时隧道,让内网服务器通过本地开发机的网络访问公网资源(如阿里云镜像源、Maven 中央仓库等)。


💡 技术原理:SSH 反向隧道

SSH 不仅可以用于远程登录,还内置了强大的隧道功能。其中 -R 参数用于创建反向隧道。

原理流程

  1. 本地电脑开启一个流量转发服务(通常使用 HTTP 或 SOCKS 协议)。
  2. 通过 SSH 建立连接,将服务器的某个端口(如 8888)映射到本地电脑的转发端口。
  3. 服务器配置环境变量,将网络请求发送给自身的 8888 端口。
  4. 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

🚧 常见问题排查

  1. 连接被拒绝 (Connection Refused)

    • 检查本地电脑的端口(如 7890)是否开启。
    • 检查本地电脑的防火墙设置,确保允许 Docker 容器或 SSH 进程访问该端口。
    • 部分本地网络服务默认只监听 127.0.0.1,需开启"允许局域网连接"或监听 0.0.0.0
  2. 速度慢

    • 受限于 SSH 协议的加密解密开销以及本地电脑的上行带宽,该方案适合传输代码、配置文件或普通软件包,不建议传输超大文件。

🎉 总结

通过 SSH 反向隧道,我们无需在内网防火墙上开洞,利用现有的 SSH 通道即可巧妙解决内网服务器的公网资源访问问题。这对于隔离环境下的 DevOps 运维非常实用。

希望这篇文章能帮到你!如果有疑问,欢迎在评论区留言交流。


(本文归档于:服务器运维 / Linux技巧 / 网络配置)

相关推荐
fyakm3 小时前
K8s故障排查:常见问题定位与解决
docker·容器·kubernetes
abcy0712133 小时前
k8s ipc-namespace进程间通信隔离类型详解
docker·容器·kubernetes
Justice link3 小时前
K8S基本配置
运维·docker·容器
月亮不营业啦3 小时前
docker 教程(带详细图文)
docker
若涵的理解3 小时前
一文读懂K8S kubectl 命令,运维小白必看!
运维·docker·kubernetes
java_logo3 小时前
2025 年 11 月最新 Docker 镜像源加速列表与使用指南
linux·运维·docker·容器·运维开发·kylin
XMYX-04 小时前
Ubuntu 22.04.5 LTS 安装 Docker 29.1.5(阿里云镜像,生产环境实战)
ubuntu·阿里云·docker
Sombra_Olivia4 小时前
Ubuntu22.04 安装Docker Vulhub遇到的问题
web安全·docker·vulhub
小镇学者5 小时前
【python】python项目是如何部署到服务器上的
服务器·python·github