基于 SSH 隧道实现端口转发/内网穿透
基于 SSH 隧道实现端口转发/内网穿透
lololowe1. 本地端口转发
本地端口转发指的是将本地机器的某个端口的所有请求通过ssh隧道转发到远程主机的某个端口上,相当于将远程主机的某个端口映射到了本地机器的某个端口上,访问本机的该端口就相当于访问远程主机的相关端口。
本地端口转发的命令格式如下:
1 | ssh -f -N -L local_port:remote_host:remote_port user@ssh_server |
-f
: 后台执行ssh指令N
: 不执行远程指令(不进入远程shell)L
: 本地端口转发,local_port
是本地主机的端口,remote_host
是远程主机的IP地址(或者是远程主机所在内网的其他主机的IP地址),remote_port
是远程主机或其同内网某主机的端口
例如, 由于远程主机的安全组设置不允许访问http的80端口, 但可以访问SSH的22端口, 那么便可以通过使用SSH的-L
选项将远程主机的80端口的流量跑在远程主机的22端口上, 具体来说就是将本地机器的8080端口(也可以指定其他端口)的所有请求通过ssh隧道转发到远程主机的80端口。这样, 在本机浏览器访问 http://127.0.0.1:8080, 实际上就是在访问远程主机的http服务。
要将本地8080端口的流量转发到远程主机的80端口, 可以使用以下命令:
1 | ssh -f -N -L 8080:127.0.0.1:80 root@ssh_server |
如果需要本地机器所在内网的其他主机也可以通过访问本机的8080端口来访问远程主机上的80端口上的http服务, 则可以在local_port前绑定本机IP地址(默认为127.0.0.1)。
要终止端口转发, 需要执行ps -ef | grep "ssh -f"
来查找端口转发进程的PID, 并使用kill -9 [PID]
命令来强制终止它。
ssh 支持同时使用多个-L
选项, 也就是说可以同时将多个本地端口转发到远程主机上。
remote_host
如果设置成远程主机所在内网的其他主机的IP地址,则远程服务器就相当于跳板机。
2. 远程端口转发
远程端口转发指的是将远程主机的某个端口的所有请求通过ssh隧道转发到本地机器的某个端口上,这有点类似于反弹shell,。
远程端口转发的命令格式如下:
1 | ssh -f -N -R remote_port:local_host:local_port user@ssh_server |
-f
: 后台执行ssh指令N
: 不执行远程指令(不进入远程shell)R
: 远程端口转发,remote_port
是远程主机的端口,local_host
是本地主机的IP地址(或者是本地主机所在内网的其他主机的IP地址),local_port
是本地主机或同内网某主机的端口
例如需要让远程主机访问到本地运行的http服务, 可以在本机执行以下命令:
1 | ssh -f -N -R 8080:127.0.0.1:80 root@remote_port |
之后便会将远程主机的8080端口的所有请求转发到本地机器的80端口。在远程服务器上访问 http://localhost:8080 等同于访问到本地机器的http服务。如果在remote_port前面绑定了远程主机的公网IP地址, 那么就相当于远程主机反向代理了本地机器的Web服务。
3. 双向端口转发
正向/反向端口转发都是单向的, 只是方向不同, 一个是由本地向远程转发请求来访问远程资源, 另一个是由远程向本地转发请求来访问本地资源。
如果需要双向通信, 那么就需要同时设置两者。要想畅通无阻地互相访问两者的资源, 还是建议使用专业的内网穿透工具, 比如ZeroTier和FRP(https://gofrp.org/zh-cn/), 使用的是虚拟专用网VPN技术。
4. 动态端口转发
动态转发指的是将本地机器的某个端口作为socks5代理, 发到此端口上的所有数据都会通过ssh隧道转发到远程主机上进行处理。
命令格式如下:
1 | ssh -f -N -D local_port user@ssh_server |
直接上演示:
转发前的IP地址:
建立转发:
转发后的IP:
浏览器需要使用ssh的socks5代理的话,可以借助 Proxy SwitchyOmega 3 扩展在不修改系统代理的情况下使用代理。
注意:有想法的可能已经想到可以使用动态端口转发在ssh隧道(海外服务器)上进行科学上网,这种方式在多年前是可行的,但现在已经不可靠了,原因是被GFW封禁的网站基本都被DNS污染了,解析出来的IP都是不可访问的…
5. SSH Config
如果经常使用端口转发的话,可以将其写入到 ~/.ssh/config
配置文件中,省去在命令中添加选项和参数:
1 | Host example # 别名 |
参考: