SSH反向隧道
SSH反向隧道是一种通过SSH协议将内网服务暴露到公网的技术,尤其适用于内网主机没有公网IP的情况。以下是详细的讲解:
1. 基本概念
- 反向隧道(Reverse Tunnel):与传统SSH隧道(内网主机作为客户端连接外网)不同,反向隧道由内网主机主动发起连接,将本地端口映射到外网服务器,使外网能够访问内网服务。
- 核心参数:使用SSH的
-R
选项实现远程端口转发。
2. 工作原理
- 内网主机主动连接外网服务器:内网主机通过SSH连接到外网服务器,并建立反向隧道。
- 端口绑定:将外网服务器的指定端口转发到内网主机的本地端口。
- 数据转发:外部请求访问外网服务器的指定端口时,数据通过SSH隧道转发到内网主机。
3. 命令格式
ssh -R <远程端口>:localhost:<本地端口> <外网用户>@<外网服务器> -Nf
- 示例:将内网的80端口映射到外网服务器的8080端口:
ssh -R 8080:localhost:80 user@example.com -Nf
- 参数说明:
-R
:远程端口转发。-N
:不执行远程命令。-f
:后台运行。
4. 外网服务器配置
- 修改
sshd_config
:确保允许远程端口绑定。# 在/etc/ssh/sshd_config中添加: GatewayPorts yes
- 重启SSH服务:
sudo systemctl restart sshd
5. 保持连接稳定
- Autossh工具:自动重连断开的SSH会话。
autossh -M 0 -R 8080:localhost:80 user@example.com -Nf
- Cron定时任务:定期检查连接状态。
6. 典型应用场景
- 访问内网Web服务:将内网Web服务器的80端口映射到外网。
- 远程SSH到内网主机:映射内网主机的22端口到外网服务器,通过外网SSH接入内网。
外网用户连接:ssh -R 2222:localhost:22 user@example.com
ssh -p 2222 localhost
7. 安全注意事项
- 最小化暴露端口:仅转发必要端口。
- 使用密钥认证:避免密码泄露,配置SSH密钥对。
- 防火墙规则:限制外网端口访问的IP范围。
8. 测试与验证
- 检查端口监听:
netstat -tuln | grep 8080 # 外网服务器执行
- 访问测试:
curl http://example.com:8080 # 应返回内网服务的响应
9. 进阶配置
- 多端口转发:多个
-R
参数或动态转发(-D
)。 - 通过反向隧道建立VPN:结合
sshuttle
等工具实现更全面的网络访问。
10. 与VPN的区别
- SSH反向隧道:轻量级,适合单个服务或临时访问。
- VPN:全局网络访问,适合长期或复杂需求。
总结
SSH反向隧道通过内网主机主动建立连接,解决了NAT穿透问题,是临时暴露内网服务的有效方案。正确配置sshd
、使用autossh
保持连接、严格的安全措施是其稳定运行的关键。
autossh (推荐)
使用 autossh
可以更稳定地维持 SSH 反向隧道(即从内网穿透到公网服务器),尤其适合需要长期保持连接的场景。以下是详细步骤:
1. 安装 autossh
在本地机器(需要穿透的内网机器)上安装 autossh
:
sudo apt update && sudo apt install autossh # Ubuntu/Debian
sudo yum install autossh # CentOS/RHEL
2. 生成 SSH 密钥对并配置免密登录
确保本地机器可以通过密钥登录到公网服务器(目标跳板机):
ssh-keygen -t ed25519 # 生成密钥对
ssh-copy-id user@remote-server.com # 将公钥复制到公网服务器
3. 建立反向隧道
使用以下命令创建反向隧道:
autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -N -R 2222:localhost:22 user@remote-server.com
参数解释:
-M 0
: 禁用 autossh 的默认监控端口(适用于新版本)。-o ServerAliveInterval 30
: 每 30 秒发送一次心跳包,保持连接。-o ServerAliveCountMax 3
: 如果连续 3 次心跳无响应,则断开并重连。-N
: 不执行远程命令(仅建立隧道)。-R 2222:localhost:22
: 将远程服务器的2222
端口转发到本地的22
端口。
4. 验证隧道是否成功
在公网服务器上检查是否监听了 2222
端口:
ss -tuln | grep 2222
输出类似:
LISTEN 0 128 127.0.0.1:2222 0.0.0.0:*
5. 通过反向隧道访问内网服务
从公网服务器通过本地端口访问内网机器的 SSH 服务:
ssh -p 2222 localuser@localhost
其中 localuser
是内网机器的用户名。
6. 配置为后台服务(开机自启)
创建 systemd 服务文件(如 /etc/systemd/system/autossh-tunnel.service
):
[Unit]
Description=AutoSSH Reverse Tunnel
After=network.target
[Service]
User=your_local_username
ExecStart=/usr/bin/autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -N -R 2222:localhost:22 user@remote-server.com
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
启动并启用服务:
sudo systemctl daemon-reload
sudo systemctl start autossh-tunnel
sudo systemctl enable autossh-tunnel
7. 其他场景示例
转发 HTTP 服务:
将内网的 80 端口转发到公网服务器的 8080 端口:
autossh -M 0 -N -R 8080:localhost:80 user@remote-server.com
转发数据库服务:
将内网 MySQL(3306 端口)转发到公网服务器:
autossh -M 0 -N -R 3306:localhost:3306 user@remote-server.com
注意事项
-
防火墙配置:
- 确保公网服务器允许入站流量访问转发的端口(如
2222
)。 - 内网机器的 SSH 配置需允许端口转发(检查
/etc/ssh/sshd_config
中AllowTcpForwarding yes
)。
- 确保公网服务器允许入站流量访问转发的端口(如
-
安全性:
- 使用非默认端口(如
2222
)降低被扫描的风险。 - 结合
-L
和-R
实现双向隧道(如果需要)。
- 使用非默认端口(如
-
调试命令:
- 查看 autossh 日志:
journalctl -u autossh-tunnel
。 - 手动调试时添加
-v
参数:autossh -v ...
。
- 查看 autossh 日志:
通过以上步骤,你可以建立一个稳定的 SSH 反向隧道,并通过公网服务器安全访问内网服务。