SSH 进阶:密钥管理、多机配置、端口转发与文件传输

第一篇笔记里 SSH 只讲到「能连上」,这篇补上真正提升效率的部分:多机管理、转发、传文件。

一、密钥:用 ed25519,一把钥匙一台机

bash
ssh-keygen -t ed25519 -C "baize@macbook"
# 一路回车即可,建议设置 passphrase(钥匙丢了还有一层保护)

生成的是一对:id_ed25519(私钥,绝不外传)和 id_ed25519.pub(公钥,放到服务器上)。

把 passphrase 交给钥匙串管理,就不用每次输:

bash
ssh-add --apple-use-keychain ~/.ssh/id_ed25519   # macOS
ssh-add ~/.ssh/id_ed25519                        # Linux(需先启动 ssh-agent)

不要用同一个密钥给所有机器。至少按「用途」分开:个人服务器一把、公司一把、GitHub 一把。

二、ssh config:一次配置,终身省心

~/.ssh/config 是最值得花十分钟的配置文件:

nginx
# 通用设置放最上面
Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3
    Compression yes
    AddKeysToAgent yes

# 主服务器
Host baize
    HostName 1.2.3.4
    Port 2222
    User baize
    IdentityFile ~/.ssh/id_ed25519

# 跳板机后面的内网机器
Host inner
    HostName 10.0.0.5
    User baize
    ProxyJump baize

配置完之后:

bash
ssh baize          # 代替 ssh -p 2222 baize@1.2.3.4
ssh inner          # 自动跳板,一条命令进内网
scp ./a.txt baize:/tmp/

三、端口转发:临时访问内网服务的救命招

三种转发,记住一句话就够:-L 把远程带到本地,-R 把本地带到远程,-D 是 socks 代理

bash
# 本地转发:把远程的 3306 映射到本机 13306
# 场景:数据库只监听 127.0.0.1,想在本地用 GUI 客户端连
ssh -L 13306:127.0.0.1:3306 baize -N -f
# 之后连 localhost:13306 就等于连服务器的 3306

# 远程转发:把本机的 3000 暴露到服务器的 8080
# 场景:本地开发要给别人演示 / 收 webhook
ssh -R 8080:127.0.0.1:3000 baize -N -f

# 动态转发:起一个 socks5 代理
ssh -D 1080 baize -N -f
# 浏览器配 socks5://127.0.0.1:1080,流量就走服务器出口

参数说明:

参数含义
-N不执行远程命令,只做转发
-f后台运行
-L本地转发 local:remote
-R远程转发
-D动态代理

-R 默认只绑定远程的 127.0.0.1。想让外网能访问,需要在服务器 sshd_config 里设 GatewayPorts yes

四、传文件:scp 简单,rsync 更聪明

bash
# 单文件
scp -P 2222 ./site.zip baize@host:/tmp/
scp baize:/var/log/nginx/error.log ./

# 整个目录:优先用 rsync,只传差异,支持断点
rsync -avz --delete ./dist/ baize:/var/www/baize/

rsync 常用参数:

参数含义
-a归档模式,保留权限/时间/软链
-v显示过程
-z传输时压缩
--delete删除目标端多余的文件(先加 --dry-run 试跑
-P显示进度 + 支持断点续传
--exclude排除文件
bash
# 先看会删什么,确认无误再真跑
rsync -avz --delete --dry-run ./dist/ baize:/var/www/baize/

# 排除 node_modules 和 .git
rsync -avz --exclude "node_modules" --exclude ".git" ./ baize:/srv/app/

五、常见报错与解法

报错原因与解法
Permission denied (publickey)公钥没放对 / 权限太开放:chmod 700 ~/.ssh; chmod 600 ~/.ssh/authorized_keys
WARNING: UNPROTECTED PRIVATE KEY FILE私钥权限不对,chmod 600 id_ed25519
Host key verification failed服务器重装过,删掉本地 ~/.ssh/known_hosts 里对应行
Too many authentication failures本地钥匙太多,ssh -o IdentitiesOnly=yes 指定一把
连上就断ServerAliveInterval 60,或路由器 NAT 超时太短
bash
# 删掉某个 host 的旧指纹
ssh-keygen -R 1.2.3.4

# 调试连接过程,卡在哪一步一目了然
ssh -vvv baize

六、安全补充

  • 服务器上禁用密码登录后,私钥就是唯一凭证,务必备份到加密的地方;
  • ~/.ssh/config 里可以给高危机器单独限制:IdentitiesOnly yesConnectTimeout 10
  • 团队场景下用 ~/.ssh/authorized_keys 里加 command= 前缀限制该钥匙只能执行固定命令。
bash
# 只允许 rsync,且限定目录(authorized_keys 里的一行)
command="rsync --server -vlogDtprz . /var/www/baize/" ssh-ed25519 AAAA...