通过 SSH 实现云服务器代理到本机
通过 SSH 转发到本机
有时候,我们可能需要在云服务器上安装一些软件,但由于网络问题(内网限制等)导致无法下载。此时如果本地计算机恰巧能访问对应资源(或者有能访问对应资源的代理),那我们可以通过 SSH 实现端口转发,将云服务器的请求转发到本地计算机再中转出去从而解决这一问题。
此方法还可用于"内网中某服务器想安装东西却无法下载,但内网中的本机可以下载"等情况(尽管这种情况并不多见)。
注:本文章不涉及任何翻墙内容,仅从技术层面讨论 SSH 的端口转发功能,请大家遵守网络守则,共同营造一个良好的网络氛围与安全的网络环境。
我的思路为 服务器:端口 a -> 本地计算机:端口 b -> 流量中转软件 -> 目标资源
可以使用不做任何配置的 clash-verge-rev 或者 v2r*yN 作为中转的软件(或者其他能将流量转出去的软件也行)
如果本地计算机的代理软件端口为 7890,则可以将云服务器 1080 端口转发到本机 7890 端口:
ssh -R 1080:127.0.0.1:7890 用户名@云服务器IP
# 或者(服务器IP是可以省略的)
ssh -R 云服务器IP:1080:127.0.0.1:7890 用户名@云服务器IP
在 Termius 中可以通过
Port Forwarding
功能实现,和上面的代码差不多,更方便一点
此时我们在服务器上使用curl IP查询网站
加上转发参数,查看当前 IP 会发现变成了本机计算机的 IP
curl 4.ipw.cn -x 127.0.0.1:1080
curl 4.ipw.cn --socks5 127.0.0.1:1080
下面是依次为基准延伸出去的拓展和记录
SSH 远程操作与端口转发
SSH 端口转发(Port Forwarding)可以通过加密的 SSH 通道在本地和远程主机之间转发网络流量
有三种主要类型:
- 本地端口转发(Local Port Forwarding)
- 远程端口转发(Remote Port Forwarding)
- 动态端口转发(Dynamic Port Forwarding)
1. 本地端口转发到远程服务器
使用 -L
参数可以将本地计算机上的特定端口流量转发到远程服务器上的特定端口。(本地端口->远程端口)
通常用于访问公司内网中的服务器或服务(比如自己放了台电脑在公司,就可以通过这台电脑访问公司内网)
假设 host1
是本地主机,可以访问外部网络,host2
是公司办公电脑,在内网且但可以访问外部网络,host3
是公司主机(比如内部数据库)也在内网但无法访问外部网络。此时 host1
就可以通过 host2
来访问 host3
。注:host1 和 host2 可以通过某些方式连接到一个局域网来互相进行访问(例如 tailscale 等工具)
# 在 host1 上运行
ssh -L 端口2:host3:端口3 user@host2
上面的代码可以将 host2
的流量可以通过 host2 的端口 2 转发到 host3 的端口 3。
注:此时 host3
的 IP 是相对于 host2
的来说的,也就是说 host3
可以是 192.168 开头的某机器,也可以是 localhost(也就是host2自己)。下面是例子:
例如本地计算机需要通过 SSH 访问远程服务器 remote_host
上的 localhost:3306
(MySQL 数据库端口),并希望将其映射到本地计算机的端口 8888
。
ssh -L 8888:localhost:3306 user@remote_host
这样就能在本地计算机通过 localhost:8888 访问远程服务器上的 MySQL 服务。此时 SSH 命令中的 localhost 是以 remote_host 视角来看的的
2. 远程端口转发到本地
使用 -R
参数可以将远程机器上的特定端口流量转发到本地主机的特定端口。(远程端口->本地端口)
通常用于允许远程计算机访问只有本机网络可以访问的东西。
假设需要将本地计算机上的 localhost:8080
(例如一个本地 Web 服务器)暴露给远程服务器 remote_host
的端口 9090
。
ssh -R 9090:localhost:8080 user@remote_host
这样远程服务器上的用户能够通过 localhost:9090
访问你的本地 Web 服务。此时 SSH 命令中的 localhost 是以 本地主机 视角来看的的
3. 本地动态端口转发到远程服务器
使用 -D
参数可以通过创建一个 socks 服务来动态地转发流量。(本地端口->远程机器中转->目标资源)
可以用于访问多个远程服务,上面两种都是一个端口转发另一个端口,而这个是通过 SSH 将流量从远端中转出去(类似于 ss/ssr 等)。
假设需要在本地计算机的 1080
端口创建一个 socks 服务,并通过远程服务器 remote_host
转发流量。
ssh -D 1080 user@remote_host
这条命令会创建一个 socks 服务,可以在本地计算机的浏览器或其他应用程序中配置使用 localhost:1080
作为代理服务器,这样就会通过 remote_host
转发流量。
建立连接之后,可以在本地电脑使用 curl 命令测试(在 curl 中,socks 可以用 --socks5
参数指定):
# 用 -x 指定 socks5 协议(-x 默认指定为 http)
curl 4.ipw.cn -x socks5://127.0.0.1:1080
# 直接指定 socks5 协议
curl 4.ipw.cn --socks5 127.0.0.1:1080
其他参数
-
n 表示关闭标准输入
-
q 表示安静模式。消除所有的警告和诊断信息
-
C 表示压缩数据。在慢速连接上很有用,但在高速网络上反而会降低速度
-
T 表示不为这个连接分配远程终端(TTY)
-
N 表示只连接远程主机,不打开远程 shell(不执行远程命令)
以上参数可以配合使用,比如下面命令表示这个连接只用来传数据,不执行远程操作。
ssh -TN -D 1080 user@remote_host
此外视需要还可以增加 -f 参数使 SSH 连接成功后转入后台运行。这样一来就可以在不中断 SSH 连接的情况下,在本地机器执行其他 shell 操作。
注:这些 SSH 没有断线重连功能,链接断了命令就退出了,所以需要些脚本监控重启,或者其他工具保持链接。
临时代理配置
Linux 服务器可以使用以下命令来设置临时代理(当前会话生效)
export http_proxy=http://127.0.0.1:1080
export https_proxy=https://127.0.0.1:1080
# 或者直接用下面这行
export all_proxy=127.0.0.1:1080
如果配置了代理,想方便的启动和查看,那么可以在当前终端配置脚本(例如~/.bashrc 和 ~/.zshrc
)中添加:
# 为 curl wget git 等设置代理
proxy () {MY_PROXY="127.0.0.1:1080"export all_proxy=$MY_PROXY#export http_proxy=http://$MY_PROXYV#export https_proxy=https://$MY_PROXY#export ftp_proxy=$MY_PROXY## 无需代理的主机或域名;可以使用通配符;多个时使用","号分隔#export no_proxy="localhost, 127.0.0.1, ::1"
}# 取消代理
unproxy () {unset all_proxyunset http_proxyunset https_proxyunset ftp_proxyunset no_proxy
}# 查看代理
myproxy () {echo $all_proxyecho $http_proxyecho $https_proxyecho $ftp_proxyecho $no_proxy
}
这样就能在命令行使用 proxy
命令打开、unproxy
命令关闭、myproxy
命令查看代理。(记得重开一下终端或者刷新一下环境)
测试代理
curl 的 -x
参数是 --proxy
的缩写,用于配置代理
本地得用全局代理,或者空配置文件(因为测试的网址可能在本地代理软件的规则中,于是不会走代理)
# --proxy [protocol://]host[:port]
curl 4.ipw.cn -x socks5://127.0.0.1:1080
# 或者下面这个
curl cip.cc -x socks5://127.0.0.1:1080# 直接指定socks5协议
curl 4.ipw.cn --socks5 127.0.0.1:1080
关于登录
SSH 在第一次登录时,由于无法确认 host 主机的真实性,会显示连接主机的密钥指纹,问是否确认接受新的主机密钥(为了防止中间人攻击)
如果有物理访问权限或者可以通过其他安全途径访问服务器,可以使用以下类似的命令来主机秘钥指纹,以便于核对
# 查看ED25519主机秘钥指纹
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
当输入 yes 接收新的主机指纹后,会保存在 ~/.ssh/known_hosts
文件中,Windows 是 C:/Users/用户名/.ssh/known_hosts
文件,这个文件会保存可信赖的远程主机的公钥。
注:当远程主机重装系统或者手动更改主机密钥之后,SSH 连接会发现指纹不匹配从而连接失败,此时在确认访问途径安全的情况下,可以使用 ssh-keygen -R 远程主机地址
来删除旧密钥条目。登录之后可以使用 ls -l /etc/ssh/ssh_host_*
查看主机秘钥变更的时间。
参考链接
- SSH 原理与运用(二):远程操作与端口转发 - 阮一峰的网络日志 (ruanyifeng.com)
- SSH 命令的三种代理功能(-L/-R/-D) - 苍青浪 - 博客园 (cnblogs.com)
- Linux 服务器使用本地 http 代理访问国外源 - Chancel’s blog
- 如何在 Termius 中添加带有端口转发的 ssh 命令(使用 -L、-R、-D)_termius 端口转发-CSDN 博客
- Linux 系统设置全局代理(http 代理,socks 代理)_export sock proxy-CSDN 博客