ssh端口转发的几种常用使用方式【本地端口转发、远程端口转发、反向端口转发、动态端口转发】
文章目录
- 说明
- 本地端口转发
- 远程端口转发
- 反向端口转发
- 远程端口转发和反向端口转发区别
- 动态端口转发(Dynamic Port Forwarding)
- 非交互模式使用说明
说明
- SSH 端口转发(Port Forwarding)是 SSH 协议的一项重要功能,通过加密的 SSH 连接将网络端口的数据进行转发,实现安全的网络访问或绕过网络限制。它主要分为下面几种类型:
- 本地端口转发
- 远程端口转发
- 反向端口转发
- 动态端口转发
本地端口转发
-
本地端口转发(Local Port Forwarding)
作用是将本地主机的某个端口数据,通过 SSH 连接转发到远程服务器的目标端口(可以是远程服务器自身,也可以是其可访问的其他主机)。 -
适用场景:访问远程服务器背后的私有服务(如数据库、内网 Web 服务)。
-
命令格式:
ssh -L [本地IP:]本地端口:目标主机:目标端口 用户名@SSH服务器IP【当前主机用户名和ip】 #本地IP 可选,默认是 localhost(仅本地可访问),若填 0.0.0.0 则允许其他主机访问该本地端口。
-
展示,我这用内网web服务做说明
[root@ccx .ssh]# yum -y install httpd
[root@ccx .ssh]# systemctl restart httpd
[root@ccx .ssh]# curl 192.168.110.130【这个有内容,网页访问不了记得关防火墙】
[root@ccx ~]# cd /var/www/html/ 【改下默认参数,方便后面实验】
[root@ccx html]# echo 192.168.110.130 > index.html
[root@ccx html]# systemctl restart httpd
[root@ccx html]# curl localhost
192.168.110.130#现在开始创建一个把我80端口映射为8000端口的转发
[root@ccx ~]# ssh -L 8000:localhost:80 root@192.168.110.130
#这个就是将我主机的80端口映射为8000端口,只能通过最后面定义的地址访问,192.168.110.130和localhost其实都是一样的意思
#只是我为了展示区别将root@localhost改为了root@192.168.110.130而已[root@ccx ~]# ss -ntlp | grep 8000 【端口正常】
[root@ccx .ssh]# curl 192.168.110.130:8000 【有内容,去浏览器访问,无法访问是正常的】
[root@ccx ~]# ssh -L 0.0.0.0:8000:localhost:80 root@192.168.110.130【这是所有ip都可以访问,在去浏览器,可以访问了】
像这种使用场景不管是数据库还是网页,一般使用场景就是你改了默认端口,现在别人临时要用,但又不想别人知道你真实的端口,所以就可以通过这种方式做个端口转发,让别人用你自定义的端口。
远程端口转发
-
远程端口转发(Remote Port Forwarding)
-
和上面本地端口转发一样的意思,只是转发的端口和目标主机有变化
ssh -L [远程IP:]远程端口:目标主机:目标端口 用户名@SSH服务器IP【当前主机用户名和ip】 #远程IP 可选,默认是 localhost(仅远程服务器自身可访问),若填 0.0.0.0 则允许其他主机访问该远程端口。
-
先简单说下转发到外部地址,如转发到baidu.com
[root@ccx ~]# ssh -L 0.0.0.0:8000:www.baidu.com:80 root@192.168.110.130 [root@ccx ~]# curl 192.168.110.130:8000 #但这种大概率是不能访问的,因为转发地址有限制,但同理,我们可以在别的主机上转发我们内部地址
-
我的网页服务是安装在130上的,现在我去129上转发,转发地址用我130的ip【生产环境中,你有外网ip或绑定ip的域名,直接将转发地址改为你的域名,就能实现端口转发了】
[root@ccx ~]# ssh -L 0.0.0.0:8000:192.168.110.130:80 root@192.168.110.129 #允许所有ip访问,模拟端口为8000,转发地址和其真实端口。 后面是当前主机root用户名,和当前主机ip地址。像这样就可以访问我当前这台ip的8000端口了,转发到130的80端口上 [root@ccx ~]# ss -ntlp | grep 8000 【当前主机8000端口存在,转发正常】 [root@ccx ~]# curl 192.168.110.129:8000 【访问正常,去浏览器访问没问题】
这个就是远程端口转发,很简单很实用吧
反向端口转发
-
ssh -R [远程IP:]远程端口:目标主机:目标端口 用户名@SSH服务器IP
远程IP 可选,默认是 localhost(仅远程服务器自身可访问),若填 0.0.0.0 则允许其他主机访问该远程端口。 -
如果你有一台无法通过Internet访问到的主机,但是又希望其他用户可以访问这台主机上的服务,那可以通过反向端口转发来实现。
-
如果你能够使用SSH访问一台可以通过Internet访问的远程主机,那么就可以在这台主机上设置反向端口转发,将流量转发到运行该服务的本地主机。如我下面129是可以外网访问的,就可以再129上将130这台外网无法访问的主机服务进行转发到129上
-
反向端口转发需要配合-g参数使用,-g 覆盖 SSH 服务的默认限制,强制让 0.0.0.0 配置生效
[root@ccx ~]# ssh -g -R 0.0.0.0:8000:192.168.110.130:80 root@192.168.110.129 [root@ccx ~]# ss -ntlp | grep 8000 【现在监听地址是所有,如果不加-g,监听地址可能会被限制为127.0.0.1:8000】 LISTEN 0 128 *:8000 *:* users:(("sshd",pid=10269,fd=8)) LISTEN 0 128 :::8000 :::* users:(("sshd",pid=10269,fd=9)) [root@ccx ~]# [root@ccx ~]# curl 192.168.110.129:8000 192.168.110.130 [root@ccx ~]#
-
如果不加-g参数监听就变成127.0.0.1了
[root@ccx ~]# ssh -R 0.0.0.0:8000:192.168.110.130:80 root@192.168.110.129
root@192.168.110.129's password:
Last login: Sat Jul 26 14:04:18 2025 from 192.168.110.129
hello times: Sat Jul 26 14:19:06 CST 2025
hello wegoing...
[root@ccx ~]# ss -ntlp | grep 8000
LISTEN 0 128 127.0.0.1:8000 *:* users:(("sshd",pid=10503,fd=9))
LISTEN 0 128 ::1:8000 :::* users:(("sshd",pid=10503,fd=8))
[root@ccx ~]#
#这时候129也不能访问了
[root@ccx ~]# curl 192.168.110.129:8000
curl: (7) Failed connect to 192.168.110.129:8000; Connection refused
[root@ccx ~]#
#只能通过127.0.0.1访问
[root@ccx ~]# curl 127.0.0.1:8000
192.168.110.130
[root@ccx ~]#
远程端口转发和反向端口转发区别
-
简单来说,其实使用远程端口转发(-L)参数可能更合适一些,因为都能达到我们想要的目的。现在我举个例子说明一下
-
- 使用 -L(本地转发)的场景
你在办公室(无法直接访问家里的 NAS 服务器 192.168.1.100),但家里有一台公网 VPS(4.3.2.1):
# 在办公室机器上执行端口转发 ssh -L 0.0.0.0:8000:192.168.1.100:80 root@4.3.2.1
然后在办公室浏览器访问
http://4.3.2.1:8000
,就能间接访问家里 NAS 的 Web 界面。 - 使用 -L(本地转发)的场景
-
- 使用 -R(反向转发)的场景
你有一台内网服务器(192.168.1.200,无公网 IP),想让外网用户访问它的 80 端口,而你有一台公网 VPS(4.3.2.1):
# 在内网服务器(192.168.1.100)上执行 ssh -R 0.0.0.0:8000:localhost:80 root@45.32.1.1
然后外网用户访问
http://4.3.2.1:8000
,就会被转发到你的内网服务器 192.168.1.100:80。 - 使用 -R(反向转发)的场景
-
-
你看,两者实现和使用方式是不是一样,仅仅是参数的区别而已。
但是有些版本主机做反向端口转发服务器需允许远程转发:
若使用 -R,远程服务器的/etc/ssh/sshd_config
需配置:GatewayPorts yes
否则默认只监听 localhost,外网无法访问。 -
总结
- -L(本地转发):让本地端口代理访问远程服务,适合 “突破本地网络限制”。
- -R(远程转发):让远程服务器端口代理访问本地服务,适合 “内网穿透”。
- 选择哪种方式,取决于你是想从本地访问远程资源,还是想让远程用户访问本地资源。
- 理解可能有点难,反正优先使用-L参数就行了,-L参数可以满足使用场景的。
动态端口转发(Dynamic Port Forwarding)
-
作用:创建一个 SOCKS 代理服务器,本地应用通过该代理访问任意远程主机和端口,所有流量通过 SSH 连接加密传输。
-
也可以突破网络限制
简单来说如当本地网络封锁了某些网站或服务时(如公司屏蔽社交媒体、特定国家 / 地区的内容),通过 -D 创建的代理可以绕过这些限制。只要远程服务器能访问目标网站,你的流量就会被伪装成从服务器发出。 -
适用场景:科学上网、访问复杂内网环境(无需指定具体端口,灵活转发)。
-
命令格式:
ssh -D [本地IP:]1080 用户名@SSH服务器IP 【因为是代理使用,所以一般不需要指定本地ip】
-D 参数(动态端口转发)的核心意义在于 创建一个通用的加密代理通道,让所有应用程序的网络流量都能通过 SSH 隧道安全传输,绕过网络限制或加密明文通信。它与 -L(本地转发)和 -R(远程转发)的最大区别在于:-D 是 “动态” 的,适用于任意协议,而 -L 和 -R 是 “静态” 的,需指定固定的目标端口。
-
如我现在 在129上创建一个130的代理
[root@ccx ~]# ssh -D 1080 root@192.168.110.130 【注意,这个1080端口是固定的,它是socks代理的端口】 [root@ccx ~]# ss -ntlp | grep 1080【新开一个129的窗口就可以看到1080端口的监听了】 LISTEN 0 128 127.0.0.1:1080 *:* users:(("ssh",pid=10801,fd=5)) LISTEN 0 128 ::1:1080 :::* users:(("ssh",pid=10801,fd=4))
[root@ccx ~]#
```
-
这个因为是个代理,所以使用场景有限制,每次使用时都需要显式指定 --socks5 127.0.0.1:1080 参数,否则 curl 会默认使用直连方式,不会通过 SOCKS 代理转发请求。因为执行命令不会自动读取系统的 SOCKS 代理配置,除非你通过环境变量或配置文件进行设置。至于配置这些就不说了,我现在演示下使用方式
-
用最常规的curl测试
在 129 上执行:通过 1080 端口的 SOCKS 代理,访问目标地址(目标地址会由 130 实际发起请求)-
如curl --socks5 127.0.0.1:1080 http://127.0.0.1:80【这里的 127.0.0.1 是 130 视角的本地地址,可以通过这种方式访问130上本地所有服务】
[root@ccx ~]# curl --socks5 127.0.0.1:1080 http://127.0.0.1:80 192.168.110.130 [root@ccx ~]#
-
也可以直接访问外部地址
[root@ccx ~]# curl --socks5 127.0.0.1:1080 baidu.com【这种访问返回的 IP 信息会显示为 130 主机的公网 IP】 <html> <meta http-equiv="refresh" content="0;url=http://www.baidu.com/"> </html> [root@ccx ~]#
-
-
再以wget方式来展示下,wget 需用 --proxy 参数指定 SOCKS 代理
wget --proxy socks5://127.0.0.1:1080 http://192.168.110.130/file.txt【通过代理下载130上的文件】 wget --proxy socks5://127.0.0.1:1080 https://example.com/image.jpg【通过代理下载公网文件】
-
浏览器也可以使用代理,不同浏览器设置方式不同,可以根据搜索你用的浏览器配置socks5代理来进行配置
-
好了这就是关于该代理的配置和使用方式,其实翻墙就是这种方式实现的,切记程序默认使用时需要手动指定代理
非交互模式使用说明
-
切记,我们上面说的所有转发,都需要依赖窗口,如果窗口关闭了,或时间长了窗口超时了,那么端口都无法使用!!!!
-
所以正常使用情况下,我们是用非交互模式来进行端口转发的
通过2个参数来实现非交互模式-f
:后台运行 SSH 进程(不占用终端)。-N
:仅建立连接,不执行远程命令(适合纯转发场景)。
-
如,我上面说的远程端口转发,以非交互模式运行【服务再130上,再129上执行下面命令】
[root@ccx ~]# ssh -fL 0.0.0.0:8000:192.168.110.130:80 root@192.168.110.129 -N
root@192.168.110.129's password:
[root@ccx ~]#
[root@ccx ~]# ps -ef | grep 192.168. 【能看到这个进程】
root 10885 1 0 14:43 ? 00:00:00 ssh -fL 0.0.0.0:8000:192.168.110.130:80 root@192.168.110.129 -N
root 10899 8336 0 14:43 pts/0 00:00:00 grep --color=auto 192.168.
[root@ccx ~]#
[root@ccx ~]# ss -ntlp | grep 8000
LISTEN 0 128 *:8000 *:* users:(("ssh",pid=10885,fd=4))
[root@ccx ~]#
- 这两个参数就和sed中加上-i参数一样哈,就不多说了。