SSH 指定端口建立隧道:打通内网访问完整教程
适用场景:数据库、后台、内网 HTTP 服务在公司/云内网,本机无法直连;通过一台有公网入口的跳板机(或任意可 SSH 的 Linux),把内网服务「映射」到本机,或让本机流量走代理访问整片内网。
1. 先搞清三件事
1.1 角色
| 角色 | 说明 | 示例 |
|---|---|---|
| 本地机器 | 你的电脑(Windows / macOS / Linux) | 笔记本 |
| SSH 服务器(跳板机) | 能 SSH 登录,且能访问目标内网 | 公网 ECS / 堡垒机 |
| 内网目标 | 真正要访问的服务 | 10.0.1.20:3306、http://192.168.1.10 |
1.2 三种常见隧道
| 类型 | 参数 | 一句话 |
|---|---|---|
| 本地转发 | -L |
本机端口 → 经 SSH → 内网某 IP:端口(最常用) |
| 远程转发 | -R |
服务器端口 → 经 SSH → 你本机某服务(反向) |
| 动态转发 | -D |
本机开 SOCKS 代理,浏览器/工具走代理即可访问可达的内网 |
日常「连 RDS / 连内网管理后台」用 -L ;想「整片内网像挂了代理一样逛」用 -D。
1.3 SSH 端口 ≠ 业务端口
- SSH 端口 :连跳板机用的端口,默认
22,改过则用-p指定。 - 业务端口 :MySQL
3306、Redis6379、HTTP80等,出现在-L/-R里。
2. 指定 SSH 端口登录
跳板机 SSH 不在 22 时:
bash
ssh -p 2222 user@跳板机公网IP
后面所有隧道命令,都把 -p 带上即可。
可选:把端口写进本机 ~/.ssh/config,以后少打字:
sshconfig
Host jump
HostName 公网IP或域名
User yourname
Port 2222
# IdentityFile ~/.ssh/id_rsa
之后:
bash
ssh jump
ssh -L 3306:10.0.1.20:3306 jump
3. 本地转发 -L:指定端口打通单个内网服务(最常用)
3.1 命令模板
bash
ssh -p <SSH端口> -N -L <本地端口>:<内网主机>:<内网端口> <用户>@<跳板机>
| 参数 | 含义 |
|---|---|
-p |
SSH 登录端口(默认 22 可省略) |
-N |
不打开远程 shell,只做转发(适合「挂着当隧道」) |
-L |
本地端口转发 |
本地端口 |
你本机监听的端口,如 3306、13306 |
内网主机 |
从跳板机视角能访问的地址(IP 或内网 DNS) |
内网端口 |
目标服务端口 |
3.2 示例:打通内网 MySQL
假设:
- 跳板机:
jump.example.com,SSH 端口2222,用户ops - 内网 MySQL:
10.0.1.20:3306
bash
ssh -p 2222 -N -L 3306:10.0.1.20:3306 ops@jump.example.com
保持该终端不要关。另开终端验证:
bash
# 本机连的是「本地 3306」,实际到内网库
mysql -h 127.0.0.1 -P 3306 -u dbuser -p
图形工具(DBeaver、Navicat、DataGrip)连接参数:
| 项 | 填法 |
|---|---|
| Host | 127.0.0.1 |
| Port | 3306 |
| 用户/密码 | 数据库账号(不是 SSH 账号) |
| SSH Tunnel | 关闭(隧道已在命令行建好,勿再开一层) |
流量路径:
本机工具 → 127.0.0.1:3306 → SSH 加密通道 → 跳板机 → 10.0.1.20:3306。
3.3 本机 3306 已被占用时
换本地端口,例如 13306:
bash
ssh -p 2222 -N -L 13306:10.0.1.20:3306 ops@jump.example.com
工具里 Host 仍为 127.0.0.1,Port 改为 13306。
3.4 一条 SSH 同时转发多个端口
bash
ssh -p 2222 -N \
-L 3306:10.0.1.20:3306 \
-L 6379:10.0.1.30:6379 \
-L 8848:10.0.1.40:8848 \
ops@jump.example.com
之后本机:
127.0.0.1:3306→ 内网 MySQL127.0.0.1:6379→ 内网 Redis127.0.0.1:8848→ 内网 Nacos
3.5 内网 HTTP / 管理后台
bash
ssh -p 2222 -N -L 8080:192.168.1.10:80 ops@jump.example.com
浏览器访问:http://127.0.0.1:8080(等价于访问内网那台的 80 端口)。
HTTPS 同理,注意证书域名可能与 127.0.0.1 不匹配,浏览器会告警,内网自测可临时忽略或改用 hosts + 自定义本地端口策略。
3.6 后台常驻(可选)
bash
# 断线重连、后台运行(需安装 autossh)
autossh -M 0 -f -N -p 2222 -L 3306:10.0.1.20:3306 ops@jump.example.com
或先用 tmux / screen 开会话再跑 ssh -N -L ...,避免关终端掉线。
4. 动态转发 -D:让「跳板机能到的内网」都能访问
只映射一两个端口时用 -L;若要访问很多内网 IP/网站(未知端口、零散后台),用 SOCKS 动态代理:
bash
ssh -p 2222 -N -D 1080 ops@jump.example.com
含义:本机 127.0.0.1:1080 提供 SOCKS5 代理,流量经跳板机出去------凡是跳板机网络能到达的地址,代理后你都能访问。
4.1 浏览器
- Chrome / Edge:可用 SwitchyOmega 等插件,代理类型 SOCKS5,主机
127.0.0.1,端口1080。 - 或系统代理指向 SOCKS5(视 OS 而定)。
设置好后,浏览器直接打开内网地址即可,例如:
text
http://10.0.1.50:3000
http://nacos.internal.company/
4.2 命令行走代理
bash
# curl
curl --socks5-hostname 127.0.0.1:1080 http://10.0.1.50/
# 部分工具
export ALL_PROXY=socks5://127.0.0.1:1080
4.3 -L 与 -D 怎么选
| 需求 | 用 |
|---|---|
| 固定连 MySQL / Redis / 某个后台 | -L,工具填 127.0.0.1:本地端口 |
| 临时逛很多内网 Web、IP 不固定 | -D + SOCKS 代理 |
| 两者都要 | 可同时:ssh -N -D 1080 -L 3306:10.0.1.20:3306 ... |
注意:
-D能访问的范围 = 跳板机路由/安全组允许到达的范围,不是魔法穿透任意隔离网段。
5. 远程转发 -R(简要)
把「你本机的服务」暴露给服务器一侧(较少用于连内网库,多用于演示/回调):
bash
ssh -p 2222 -N -R 9000:127.0.0.1:3000 ops@jump.example.com
在跳板机上访问 127.0.0.1:9000,会转到你本机的 3000。
服务器需在 sshd_config 中允许:GatewayPorts / AllowTcpForwarding 等(视需求配置)。
6. 建立隧道之后:怎么确认「内网通了」
6.1 看本机是否在听端口
bash
# Linux / macOS
ss -lntp | grep 3306
# 或
lsof -iTCP:3306 -sTCP:LISTEN
# Windows PowerShell
netstat -ano | findstr :3306
有 127.0.0.1:3306(或 0.0.0.0:3306)监听即本地转发已起来。
6.2 测连通
bash
# 通用
curl -v telnet://127.0.0.1:3306
# 或
nc -vz 127.0.0.1 3306
数据库:
bash
mysql -h 127.0.0.1 -P 3306 -u... -p
HTTP:
bash
curl -I http://127.0.0.1:8080
6.3 工具侧检查清单
- 连的是
127.0.0.1+ 你映射的本地端口,不是内网 IP(除非走了 SOCKS)。 - 不要 再开 DBeaver / Navicat 自带 SSH 隧道(与命令行
-L二选一)。 - 账号密码是目标服务的,不是 SSH 用户。
- 隧道终端仍在跑;SSH 断线后本地端口会失效。
7. 与图形工具 SSH 隧道的关系(易踩坑)
| 做法 | 是否可行 |
|---|---|
命令行已 -L 3306,DBeaver 直连 127.0.0.1:3306,关闭应用内 SSH |
✅ 推荐 |
| 命令行不建隧道,只在 DBeaver 里勾选 SSH Tunnel,Host 填内网库地址 | ✅ 也可以 |
| 命令行已占 3306,DBeaver 再开 SSH 又绑 3306 | ❌ 端口冲突 |
| 两层都开且指向混乱 | ❌ 难排查 |
原则:同一条访问路径,只保留一层 SSH 隧道。
8. 权限与安全注意
- 跳板机要对目标内网 IP:端口有出站权限(安全组 / 防火墙)。
- 服务器
sshd_config需允许转发,例如:AllowTcpForwarding yes(默认多为 yes)。 -L默认只绑在本机回环;若写成0.0.0.0:3306:...或*:3306:...,局域网他人可能连你的转发端口,生产慎用。- 不要把跳板机密钥、数据库密码写进博客或公开仓库。
- 用完关掉隧道(终端
Ctrl+C),减少暴露面。
9. 常见问题速查
| 现象 | 可能原因 | 处理 |
|---|---|---|
bind: Address already in use |
本地端口被占用 | 换本地端口,或关掉占用进程 |
| 隧道建了但连不上目标 | 跳板机到内网不通;写错内网 IP | 先在跳板机上 telnet 内网IP 端口 / nc |
Connection refused |
目标没监听;安全组拦截;端口写错 | 核对内网端口与防火墙 |
SSH 能登,-L 无效 |
AllowTcpForwarding no;权限受限 |
查 /etc/ssh/sshd_config |
| DBeaver 报 SSH/端口错误 | 与命令行隧道叠层 | 关掉应用内 SSH,只连 localhost |
| 睡醒后隧道失效 | 网络切换 / 超时断开 | 重连;或用 ServerAliveInterval / autossh |
保活示例:
bash
ssh -p 2222 -N \
-o ServerAliveInterval=30 \
-o ServerAliveCountMax=3 \
-L 3306:10.0.1.20:3306 \
ops@jump.example.com
10. 一张图串起来
text
加密 SSH(-p 指定登录端口)
┌──────────┐ ─────────────────────► ┌────────────┐ ┌──────────────┐
│ 你的电脑 │ -L 本地端口:内网IP:端口 │ 跳板机 │ ───► │ 内网 MySQL等 │
│ 工具/浏览器 │ 或 -D 1080 (SOCKS) │ (能访内网) │ │ 内网 Web 等 │
└──────────┘◄──── 127.0.0.1:本地端口 ──────────└────────────┘ └──────────────┘
11. 速查命令卡片
bash
# 指定 SSH 端口登录
ssh -p 2222 user@jump
# 单端口本地转发(MySQL)
ssh -p 2222 -N -L 3306:10.0.1.20:3306 user@jump
# 多端口
ssh -p 2222 -N -L 3306:10.0.1.20:3306 -L 6379:10.0.1.30:6379 user@jump
# 动态 SOCKS,逛内网
ssh -p 2222 -N -D 1080 user@jump
# 本机访问
mysql -h 127.0.0.1 -P 3306 -u... -p
curl http://127.0.0.1:8080
# SOCKS:浏览器代理 127.0.0.1:1080 后直接打开内网 URL
12. 小结
- 指定 SSH 端口 :
-p,或写进~/.ssh/config。 - 指定业务端口打通内网某一服务 :
-L 本地端口:内网主机:内网端口,本机用127.0.0.1:本地端口访问。 - 希望跳板机能到的内网都能访问 :
-D开 SOCKS,浏览器/工具走代理。 - 图形工具 :命令行已建
-L时,只连本地、关闭应用内 SSH 隧道。 - 连通性以「跳板机能否访问目标」为前提;隧道只是把那条路接到你的电脑上。
按本文从「单端口 MySQL」练起,再按需加上多端口与 -D,即可覆盖绝大多数远程运维与本地开发联调场景。