在 Windows 下有非常好用的 xshell 用于管理远程 Linux 服务器,并且可以非常方便的设置隧道转发以实现 socks5 代理的功能,而且 xshell 有断线重连的功能,简直不要太贴心。
但是在 mac 环境下试了很多 ssh 客户端,效果都不尽人意,试过最好的就是 FinalShell 了,也可以设置 ssh 隧道实现 socks5 代理,但就是没有断线自动重连的功能,用起来是有点憋屈的感觉。
最终还是采用了 autossh+launchd 的方案,让 mac 一开机就自动创建 socks5 代理,并且实现断线重连。
launchd: Mac OS X 系统下的用来管理整个系统的 services 和 processes 的工具。如果你需要一个程序开机自动运行,或者由于错误停止后自动重新运行,那么就可以用 launchd 来管理。
autossh: 是用来保持 ssh 一直处于链接状态的工具。可以在链接断开后自动重新链接。
一、首先需要设置免密登录远程 ssh 主机
如果你还没有创建 rsa 密钥对的话,可以使用ssh-keygen
命令创建一组密钥对,注意不用设置证书密码,否则使用密钥对时还会要求你输入密码。
ssh-keygen #回车
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): #回车或设置密钥的存储路径
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase): #回车或设置密钥的密码
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
92:9e:ae:cd:eb:40:a8:7c:ad:ac:af:89:c2:ce:16:fa root@wluat
The key's randomart image is:
+--[ RSA 2048]----+
| |
| |
| |
| . . |
| . . o S |
|.o ... o |
|+.....o |
|=o+ .= |
|=BE+.o*. |
+-----------------+
然后需要将密钥对的公钥文件发送到远程服务器上去,让远程服务器自动识别本机身份
ssh-copy-id -i ~/.ssh/id_rsa.pub -p 3222 username@58.52.98.74 #回车
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/Users/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
username@58.52.98.74\'s password: #需要你输入远程主机密码
Number of key(s) added: 1
Now try logging into the machine, with: "ssh -p '3222' 'username@58.52.98.74'"
and check to make sure that only the key(s) you wanted were added.
这样公钥就写到了远程主机的"~/.ssh/authorized_keys"文件中
关于ssh-copy-id
指令的参数解释如下
- -i 即 identity_file,指定公钥文件
- -p 即 port,指定 ssh 端口,如果是默认 22 端口可以省略
- 最后
username@58.52.98.74
是连接远程主机的用户名和主机地址
公钥发送到远程主机后立即就可以用 ssh 免密连接试试,如果报错UNPROTECTED PRIVATE KEY FILE
,是指本地私钥文件权限太开放,需要收紧权限。因为我是将自己常用的一组证书文件直接拷贝到~/.ssh/
目录下面的,所以权限不正确,需要更改权限。
chmod 700 ~/.ssh/id_rsa
二、安装 autossh
brew install autossh
安装完成后,在终端下试试直接使用 autossh
autossh -M 0 -nNT -D 0.0.0.0:10800 -i ~/.ssh/id_rsa -p 3222 username@58.52.98.74
# mac自带ssh命令本身就支持socks5转发,autossh很多参数是透传给底层ssh指令,不安装autossh可以临时用下ssh
# ssh -NT -D 0.0.0.0:10800 -p 3222 username@58.52.98.74
注意
-D 0.0.0.0:10800
,表示监听本机所有 IP 地址的 10800 端口,这样可以让局域网内其他机器可以通过本机使用代理
autossh 参数解释
- -M 服务器 echo 机制使用的端口(autossh 专用的参数,默认 ssh 没有此参数)
- -C 压缩传输数据
- -D 本机最终的 socks5 端口
- -R 将远程主机(服务器)的某个端口转发到本地端指定机器的指定端口
- -L 将本地机(客户机)的某个端口转发到远端指定机器的指定端口
- -f 后台运行
- -T 不占用 shell,不需要远程分配终端
- -n 关闭标准输入,配合 -f 参数使用
- -N 不执行远程命令
- -q 安静模式运行;忽略提示和错误
-nNT 这个几个参数最好保持,另外最好不要增加-f 参数,如果增加了 launchd 就有可能不能进行正确管理。 -i 是指定 rsa 私钥文件,如果是使用当前登录用户的私钥时可以省略,但是如果后面我们配置 launchd 是在本机用户未登录的状态下就进行连接,则必须要指定。 -p 是指定 ssh 端口
执行上面命令之后我们要达到的效果是:没有返回结果,并且命令不结束,socks5 可用,可以用 SwitchySharp for Chrome 测试。
测试成功后可以按 Ctrl + c 退出刚才状态。
三、配置 launchd 开机启动 autossh,自动连接远程主机
编辑启动配置文件ssh-socks5.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>ssh-socks5</string>
<key>ProgramArguments</key>
<array>
<string>/opt/homebrew/bin/autossh</string>
<string>-M</string>
<string>0</string>
<string>-nNT</string>
<string>-D</string>
<string>0.0.0.0:10800</string>
<string>-i</string>
<string>/Users/root/.ssh/id_rsa</string>
<string>-p</string>
<string>3222</string>
<string>username@58.52.98.74</string>
</array>
<key>KeepAlive</key>
<true/>
<key>RunAtLoad</key>
<true/>
<key>StandardOutPath</key>
<string>/Users/root/logs/ssh-socks5-out.log</string>
<key>StandardErrorPath</key>
<string>/Users/root/logs/ssh-socks5-err.log</string>
</dict>
</plist>
这个 launchd 启动配置文件可以放在 4 个地方,区别如下
- /Library/LaunchDaemons/ 由管理员定义的守护进程任务项,开机就会启动
- /Library/LaunchAgents/ 由管理员为用户定义的任务项,开机就会启动
- ~/Library/LaunchAgents/ 由用户自己定义的任务项,需要用户登录后才会启动
- /System/Library/LaunchAgents 由 Mac OS X 为用户定义的任务项,开机就会启动
编辑好启动配置文件后,可以立即加载进行测试,launchd 的加载和卸载命令如下
launchctl load ~/Library/LaunchAgents/ssh-socks5.plist
launchctl unload ~/Library/LaunchAgents/ssh-socks5.plist
如果 load 加载后发现 socks5 连接不通,可以用launchctl list | grep ssh-socks5
查看启动状态,正常状态是 0,如果是其他状态,则需要查阅资料自行排查。
需要注意的是,StandardOutPath
和StandardErrorPath
指定的日志路径必须是当前用户的可写路径,否则启动会失败,状态码是 78
到目前为止,我们就可以很轻松的使用代理了,而且不用操心代理是否掉线的问题,系统会自动去帮你重连。如果出现问题,可以根据ssh-socks5.plist
配置文件中指定的日志文件查看有无相关错误。