概览
实现 SSH 免密登录,并让云服务器流量转发到本地端口,通过代理再返回。
免密登录
打开 ~/.ssh/config,写入:
bash
Host <server ip>
HostName <server ip>
User root # 默认为 root 用户
Port 22 # SSH 默认端口
打开 Cursor 的 Remote Explorer,会看到多了 <server ip> 这个选项。
现在配置免密
-
本机生成密钥
bashssh-keygen -t ed25519 # 随便取一个文件名 -
公钥写入服务器
bashssh-copy-id ~/.ssh/id_ed25519.pub <user>@<server-ip> -
验证免密登录
打开 Cursor 的 Remote Explorer,直接点击配置的 <server ip>;也可以使用命令行:
bash
ssh <user>@<server-ip>
端口转发与代理
原理
建立与云服务器的 SSH 正向隧道后,再搭建一条反向隧道(云服务器 -> 本机)。以下以 "云服务器 1080 端口 ↔ 本机 7897 端口" 为例:
- 云服务器访问外网时,将流量统一发到 1080 端口。
- 反向隧道把 1080 端口的流量转发到本机 7897。
- 本机 7897 端口交给代理软件,按节点分发,再把结果回传给云服务器。
实现
提供三种实现方法,实现方法三选一即可, 但是前置步骤要完成
前置步骤
- 在代理软件的端口设置中开启混合端口转发(以 7897 为例)。
- 在云服务器中配置环境变量,统一走 1080 端口。编辑
~/.bashrc:
bash
# 代理配置
PROXY_SERVER="127.0.0.1"
PROXY_PORT="1080"
PROXY_URL="http://$PROXY_SERVER:$PROXY_PORT"
# 使用 curl 快速检测(1秒超时)
if curl -s -o /dev/null -w "%{http_code}" --max-time 1 -x "$PROXY_URL" https://www.google.com 2>/dev/null | grep -q "200"; then
export http_proxy="$PROXY_URL"
export https_proxy="$PROXY_URL"
export HTTP_PROXY="$PROXY_URL"
export HTTPS_PROXY="$PROXY_URL"
echo "✓ 代理可用,已启用"
else
unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY
echo "✗ 代理不可用,直连模式"
fi
# .bashrc 中添加函数
proxy_on() {
export http_proxy="http://127.0.0.1:1080"
export https_proxy="http://127.0.0.1:1080"
export HTTP_PROXY="http://127.0.0.1:1080"
export HTTPS_PROXY="http://127.0.0.1:1080"
echo "✓ 代理已启用"
}
proxy_off() {
unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY
echo "✗ 代理已关闭"
}
proxy_test() {
echo "测试代理..."
curl --proxy http://127.0.0.1:1080 -I -s https://www.google.com
}
保存后运行 source ~/.bashrc 使其生效。
- 编辑
/etc/ssh/sshd_config,将以下参数取消注释并设为yes:AllowTcpForwarding:允许 SSH 客户端发起本地/远程端口转发。GatewayPorts:远程端口转发可绑定0.0.0.0/::。PermitTunnel:允许基于 SSH 的三层隧道。
三种方法
注: 三种方法在云服务器上绑定的端口都是 1080, 最好用完一个方法就关闭, 而不是一起使用, 否则可能造成端口冲突
- 写入本地 SSH 配置
在~/.ssh/config中(基于免密配置)写入:
bash
Host <server ip>
HostName <server ip>
User root
Port 22
# 追加下面三条即可
RemoteForward 1080 localhost:7897
ServerAliveInterval 30
ServerAliveCountMax 3
写好后,Cursor 远程连接服务器时会自动启动反向隧道。
-
使用脚本与工具保持隧道
- 普通 SSH,一旦关闭终端会话就会断开:
bashssh -M 0 -f -N -v -o ServerAliveInterval=30 -o ServerAliveCountMax=3 \ -i ~/.ssh/<key file name> -R 1080:localhost:7897 <user>@<server ip>- 使用
autossh可以保持连接,先通过 Homebrew 安装:
bashbrew install autossh再写脚本方便启动和提示:
bash
# 文件名 start_ssh_tunnel.sh
autossh -M 0 -f -N -v -g -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -i ~/.ssh/<key file name> -R 1080:localhost:7897 <user>@<server ip>
if [ $? -eq 0 ]; then
echo -e "\033[32m✅ 隧道启动成功!\033[0m"
echo -e "📌 验证方法:"
echo -e " 1. Mac 端查看进程:ps aux | grep autossh"
echo -e " 2. 服务器端查看端口:ss -tulnp | grep :1080"
echo -e " 3. 关闭隧道:pkill autossh"
else
echo -e "\033[31m❌ 隧道启动失败!\033[0m"
echo -e "🔍 可能原因:"
echo -e " 1. autossh 未安装(执行 brew install autossh)"
echo -e " 2. 密钥路径错误(当前路径:~/.ssh/id_rsa)"
echo -e " 3. 服务器 1080 端口被占用"
fi
后续操作:
bash
# 打开端口转发
./start_ssh_tunnel.sh
# 关闭端口转发
pkill autossh
# 查看 autossh 相关进程(含 grep 本身)
ps aux | grep autossh
-
Termius 配置端口转发
在 Termius 左侧 Port Forwarding 中新建规则:
- Remote host:
<server ip> - Remote port:
1080 - Bind address:
127.0.0.1 - Destination address:
127.0.0.1 - Destination port:
7897
没搞懂 Bind address 和 Destination address 的区别 不过确认 Termius 显示
From <server ip>:1080 to 127.0.0.1:7897即表示已连通,启用后再连接服务器即可完成转发。 - Remote host:
测试
测试要使用 curl, 而不能使用 ping 因为 ping 基于 ICMP 协议, 运行在网络层,而我们配置的 SSH 端口转发 + 代理仅支持 TCP/UDP 协议,ICMP 数据包无法通过代理隧道转发
bash
# 请求国内网络
curl --proxy http://127.0.0.1:1080 -I -s https://www.baidu.com
# 请求国外网络
curl --proxy http://127.0.0.1:1080 -I -s https://www.google.com