跳转到内容

ssh

ssh(secure shell)用于登录远程主机、在远程执行命令。它同时也是 scp、rsync、git 的底层传输通道,所以把 ssh 配顺了,这几样一并省心。

Terminal window
ssh [选项] [用户@]主机 [命令]
参数 说明
用户 远程主机上的用户名,省略时用本地当前用户名
主机 域名、IP,或 ~/.ssh/config 里定义的别名
命令 给了就在远程执行完直接断开,不进入交互 shell

一次连接分四步:

  1. 建立 TCP 连接(默认 22 端口),协商协议版本和加密算法
  2. 服务端出示自己的主机公钥,客户端拿它跟 ~/.ssh/known_hosts 里记的比对。对不上就弹出那个刺眼的警告 —— 这一步防的是中间人
  3. 用户认证,依次尝试公钥、键盘交互、密码
  4. 认证通过后在这条加密连接上开若干 channel,交互 shell、端口转发、文件传输各占一个

公钥认证的关键在于私钥不出本机:私钥放本地 ~/.ssh/id_ed25519,公钥放服务端 ~/.ssh/authorized_keys。服务端发一段随机数,客户端用私钥签名,服务端用公钥验证签名。

选项 说明
-p <端口> 指定端口,默认 22。注意 scp 用的是大写 -P
-l <用户> 指定用户名,等价于 用户@主机
-i <私钥> 指定私钥文件
-J <跳板> 经跳板机连接,等价于配置项 ProxyJump
-o <项>=<值> 临时覆盖一条配置,不用改配置文件
-t 强制分配伪终端,远程要跑交互程序时必须加
选项 说明
-L <本地端口>:<目标主机>:<目标端口> 本地端口转发,把远端的服务拉到本地来访问
-R <远程端口>:<目标主机>:<目标端口> 远程端口转发,把本地的服务送到远端去
-D <端口> 动态转发,在本地开一个 SOCKS 代理
-A 转发认证代理,在跳板机上继续往下连时不必把私钥拷过去
-N 不执行任何远程命令,只做转发
-f 认证完成后转入后台
选项 说明
-v 输出调试信息,-vv、-vvv 更详细
-q 安静模式,压掉警告
-G 打印最终生效的配置后退出,不真的连接

1. 登录与远程执行

Terminal window
ssh alice@10.0.0.5
ssh -p 2222 alice@10.0.0.5
ssh alice@10.0.0.5 'df -h /'
ssh -t alice@10.0.0.5 'htop'

带命令时默认不分配伪终端,要跑 htop、vim 这类要占屏幕的程序得加 -t

2. 配好密钥,不再敲密码

Terminal window
ssh-keygen -t ed25519 -C "bdathe@laptop"
ssh-copy-id alice@10.0.0.5

没有兼容性包袱就用 ed25519,密钥短、验签快 权限要求很硬:~/.ssh 必须 700,私钥必须 600,服务端的 authorized_keys 必须 600。任何一处过松,ssh 会直接拒绝用这把钥匙,而且提示不明显

3. 用 config 把长命令收起来

~/.ssh/config
Host prod
HostName 10.0.0.5
User alice
Port 2222
IdentityFile ~/.ssh/id_ed25519
ServerAliveInterval 60
Terminal window
ssh prod
scp file.txt prod:/tmp/
rsync -av ./dist/ prod:/srv/www/

别名对 scp、rsync、git 一样生效,配一次到处用 ServerAliveInterval 定期发心跳,防止空闲连接被中间的防火墙掐掉

4. 端口转发

Terminal window
ssh -N -L 8080:localhost:3306 prod # 本地 8080 → prod 上的 3306
ssh -N -R 9000:localhost:80 prod # prod 的 9000 → 本机的 80
ssh -N -D 1080 prod # 本地 SOCKS 代理

-L 是把远端的东西拉过来,比如访问只监听 127.0.0.1 的数据库 -R 是把本地的东西送出去,比如让远端访问本机正在开发的服务 两个方向记混的时候,看字母对应的是哪一端在监听:-L 本地监听,-R 远程监听

5. 经跳板机

Terminal window
ssh -J bastion alice@10.0.0.5

比「先登跳板机再从跳板机登目标」干净,流量在跳板机上不落地 配置文件里写 ProxyJump bastion 效果相同

6. 连不上时

Terminal window
ssh -v prod
ssh -G prod # 只看最终生效的配置

常见原因:私钥或 ~/.ssh 权限过松、服务端 authorized_keys 权限过松、用户名写错、服务端禁用了密码登录 主机密钥变更的警告别顺手删掉 known_hosts 了事,先确认目标机器是不是真的重装过

  • man ssh
  • man ssh_config(客户端配置项)
  • man sshd_config(服务端配置项)