Skip to content

使用SSH隧道访问内网服务器

为什么要用SSH隧道

很多时候我们有这样的需求:

  • 本地想访问服务器内网的数据库/Redis
  • 临时让外部访问本地的测试服务
  • 想通过跳板机访问多层内网的服务

这些场景,SSH隧道都能搞定,而且比开端口安全多了。

三种转发模式详解

1. 本地转发(-L):把远程端口映射到本地

场景:服务器内网有个MySQL(3306),本地想用Navicat连。

ssh -L 13306:127.0.0.1:3306 user@server

原理

本地13306 → SSH隧道 → 服务器 → 127.0.0.1:3306

执行后,本地访问127.0.0.1:13306就相当于访问服务器上的MySQL。

实战配置:

# 后台运行,不占用终端
ssh -fNL 13306:127.0.0.1:3306 user@server

# 参数说明:
# -f 后台运行
# -N 不执行远程命令
# -L 本地转发

高级用法:访问服务器能访问的其他内网机器

# 通过跳板机访问内网192.168.1.100的Redis
ssh -L 16379:192.168.1.100:6379 user@跳板机

2. 远程转发(-R):把本地端口映射到远程

场景:本地开发了个Web服务(8080),想让外网临时访问测试。

ssh -R 18080:127.0.0.1:8080 user@server

原理

外网 → 服务器18080 → SSH隧道 → 本地8080

执行后,访问服务器IP:18080就能访问本地的8080服务。

注意:需要服务器sshd配置允许

# /etc/ssh/sshd_config
GatewayPorts yes

3. 动态转发(-D):SOCKS5代理

场景:想通过服务器代理访问一些内网资源。

ssh -D 1080 user@server

原理

本地SOCKS5代理(1080) → SSH隧道 → 服务器 → 目标地址

浏览器或其他软件配置SOCKS5代理127.0.0.1:1080,所有流量都走服务器出去。

curl测试

curl --socks5 127.0.0.1:1080 http://内网地址

实战:通过跳板机访问多层内网

公司网络架构:本地 → 跳板机 → 生产内网 → 数据库

方案一:两跳隧道

# 第一跳:本地到跳板机
ssh -L 2222:生产服务器IP:22 user@跳板机

# 第二跳:通过第一跳连接生产服务器
ssh -L 13306:127.0.0.1:3306 -p 2222 user@127.0.0.1

方案二:ProxyJump(推荐)

# SSH配置文件 ~/.ssh/config
Host 跳板机
    HostName 跳板机IP
    User your_user

Host 生产服务器
    HostName 生产内网IP
    User your_user
    ProxyJump 跳板机

# 一条命令直连
ssh -L 13306:127.0.0.1:3306 生产服务器

保持连接不断开

SSH隧道容易因为空闲而断开,加上这些配置:

# ~/.ssh/config
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
TCPKeepAlive yes

或者用autossh自动重连:

# 安装
# Ubuntu: apt install autossh
# CentOS: yum install autossh
# Mac: brew install autossh

# 使用(自动重连)
autossh -M 0 -fNL 13306:127.0.0.1:3306 user@server

常见问题排查

1. 连接被拒绝

# 检查SSH服务状态
systemctl status sshd

# 检查端口监听
ss -tlnp | grep 22

2. 远程转发不生效

# 检查sshd配置
grep GatewayPorts /etc/ssh/sshd_config

# 需要设置为yes并重启sshd

3. 连接后立即断开

# 检查是否加了-N参数
ssh -fNL 13306:127.0.0.1:3306 user@server
#  ^ 这个N很重要

说句实话

SSH隧道适合临时使用,用来调试很方便。但如果是长期需求,比如经常要远程访问内网服务、多台机器互联,配置起来就比较繁琐了。

总结

模式 参数 场景 方向
本地转发 -L 访问远程内网服务 远程→本地
远程转发 -R 暴露本地服务到远程 本地→远程
动态转发 -D SOCKS5代理 全部流量

记住这个口诀:L是拉(把远程拉到本地),R是推(把本地推到远程),D是代理。

相关命令速查:

# 本地转发:访问远程MySQL
ssh -fNL 13306:127.0.0.1:3306 user@server

# 远程转发:暴露本地Web
ssh -fNR 18080:127.0.0.1:8080 user@server

# 动态代理
ssh -fND 1080 user@server

# 查看已建立的隧道
ps aux | grep ssh