入门:OpenSSH 密钥、配置与隧道
基于 OpenSSH · 核于 2026-08
速查
- OpenSSH 是什么:远程登录与加密传输的事实标准。
ssh登录、scp/rsync拷文件、SSH 隧道穿透,背后都是它。 - 密钥认证 vs 密码:公钥放服务器(
~/.ssh/authorized_keys),私钥留本地(~/.ssh/id_ed25519)。免密登录 + 不可暴力破解,比密码更安全更便捷。 - ed25519 是首选:
ssh-keygen -t ed25519。比 RSA 更短(公钥一行 80 字符)、更快、抗量子前景更好。RSA 仅在老系统不支持 ed25519 时用(选 RSA-4096)。 - ssh-agent:私钥若设了 passphrase,每次用都要输。
ssh-agent+ssh-add把解密后的私钥缓存在内存,会话内免再输。macOS 用ssh-add --apple-use-keychain接入钥匙串。 ~/.ssh/config:把ssh -i key -p 2222 user@host浓缩成ssh prod。用Host起别名、ProxyJump多跳登录、LocalForward自动建隧道。- 端口转发三件套:
-L本地转发(把远程服务映射到本地端口)、-R反向转发(把本地服务映射到远程端口)、-D动态 SOCKS 代理。 - 权限是命门:
~/.ssh必须 700,~/.ssh/authorized_keys必须 600,私钥必须 600。权限过松 SSH 直接拒绝认证(静默失败,最难排查)。 - scp/rsync 走 SSH:
scp/rsync默认复用 SSH 通道,密钥与 config 配好后它们也自动免密。 - 边界:SSH 协议握手/加密套件理论归网络章;本叶只讲
ssh-keygen/agent/config/转发的工具操作。 - 进阶顺序:密钥与配置详解 → 隧道与端口转发 → 参考。
一、为什么用密钥而不是密码
密码认证的问题:①弱密码可被暴力破解(字典攻击);②每次登录都要输,繁琐;③密码要在网络中传输(虽在 SSH 加密通道内,但一旦机器被入侵密码就泄露)。密钥认证用非对称加密彻底解决:
- 公钥放服务器(
~/.ssh/authorized_keys),私钥留在本地(~/.ssh/id_ed25519),登录时用私钥签名证明身份,服务器用公钥验证。 - 私钥永不上传服务器,也不在网络传输——即使服务器被攻破,攻击者也拿不到你的私钥。
- 一对密钥可复用到多台服务器,配置一次永久免密。
这种「私钥签名、公钥验证」的机制是 SSH 安全的基石,也是 Git(GitHub SSH key)、scp/rsync 加密传输的通用方案。
二、生成密钥:ssh-keygen
bash
ssh-keygen -t ed25519 -C "alice@laptop" # 首选 ed25519
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_github -C "github" # 指定文件名(多账号)
ssh-keygen -t rsa -b 4096 # 仅老系统不支持 ed25519 时用-t ed25519:算法选 ed25519(Edwards-curve Digital Signature Algorithm)。公钥约 80 字符一行,私钥文件几十行,比 RSA 短得多;签名验证速度快;安全性在同等密钥长度下优于 RSA。-C "comment":注释,通常写邮箱标识这把钥匙的用途/所有者(不参与认证,纯备注)。-f:指定输出文件名,多账号场景(GitHub 个人号 + 公司号)用不同文件名区分。- passphrase:私钥的二次密码保护。即使私钥文件被盗,没有 passphrase 也无法用。代价是每次用都要输——这正是
ssh-agent要解决的问题。
生成后会有两个文件:
- 私钥
~/.ssh/id_ed25519(保密,权限 600,永不上传)。 - 公钥
~/.ssh/id_ed25519.pub(可公开,复制到服务器的authorized_keys)。
三、部署公钥:免密登录
把公钥复制到服务器的 ~/.ssh/authorized_keys 即可实现免密:
bash
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@host # 自动追加到远程 authorized_keys
# 或手动
cat ~/.ssh/id_ed25519.pub | ssh user@host "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"ssh-copy-id:自动完成「把本地公钥追加到远程 authorized_keys 并设好权限」,是最省事的方式。- 权限是命门(最容易踩的坑):远程
~/.ssh必须 700,authorized_keys必须 600。权限过松(如 644/Group 可读),SSH 的sshd会静默拒绝密钥认证(不报错,直接回退到密码),让你以为密钥配错了却查不出原因。ssh-copy-id会自动设对权限,手动操作时要chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys。
四、ssh-agent:免输 passphrase
私钥设了 passphrase 后,每次 ssh/scp/git push 都要输,繁琐。ssh-agent 解决:
bash
eval "$(ssh-agent -s)" # 启动 agent(输出环境变量)
ssh-add ~/.ssh/id_ed25519 # 把私钥加入 agent(会问一次 passphrase)
ssh-add -l # 列出已加载的密钥指纹
ssh-add -D # 删除所有已加载的密钥- 工作原理:
ssh-agent是一个常驻进程,持有已用 passphrase 解密的私钥(在内存中)。ssh连接时不再读私钥文件,而是找SSH_AUTH_SOCK指向的 agent,让 agent 代为签名——agent 已有解密后的私钥,无需再问 passphrase。 - macOS 钥匙串:
ssh-add --apple-use-keychain ~/.ssh/id_ed25519把 passphrase 存进 macOS 钥匙串,重启后自动加载,真正永久免输。 - Linux:配合
AddKeysToAgent yes(写在~/.ssh/config)首次使用时自动加入 agent。
五、~/.ssh/config:消除重复参数
每次写 ssh -i ~/.ssh/work_key -p 2222 alice@prod-server.company.com 太长。~/.ssh/config 把它浓缩成 ssh prod:
Host prod
HostName prod-server.company.com
User alice
Port 2222
IdentityFile ~/.ssh/work_key
Host github.com
User git
IdentityFile ~/.ssh/id_ed25519_github
Host bastion
HostName jump.company.com
User deploy
Host internal-* # 通配符匹配所有 internal- 开头
ProxyJump bastion # 经跳板机登录Host:你自定义的别名,之后ssh 别名即用这些参数。HostName:真实地址(IP/域名)。IdentityFile:指定私钥文件(对应-i)。ProxyJump:跳板机——先连 bastion,再从 bastion 连目标。比老的ProxyCommand简洁。LocalForward:连上后自动建本地转发隧道(见隧道节)。- 通配符:
Host internal-*匹配所有以internal-开头的别名,省去重复写 ProxyJump。
六、端口转发:三种隧道
SSH 隧道用加密通道转发 TCP 连接,是穿透防火墙、访问内网服务的利器。三种方向:
-L(Local,本地转发):把远程机器上的服务端口,映射到本地某个端口。ssh -L 5432:db.internal:5432 user@bastion后,本地连localhost:5432实际访问 bastion 能到达的db.internal:5432。用于从本地访问内网数据库/服务。-R(Remote,反向转发):把本地机器上的服务端口,映射到远程某个端口。ssh -R 8080:localhost:80 user@gateway后,远程 gateway 上的localhost:8080实际访问你本地的 80 端口。用于把本地服务暴露给远程(如内网穿透)。-D(Dynamic,动态 SOCKS 代理):ssh -D 1080 user@gateway在本地 1080 起一个 SOCKS 代理,所有走这个代理的流量经 gateway 转发。用于通用代理(翻墙/全局走远程出口)。
记忆口诀:L = Local 端口在本地、R = Remote 端口在远程、D = Dynamic 动态代理。
下一步
掌握密钥与配置基础后,下一步深入两个专题——密钥与配置详解(ssh-keygen/agent/config 的完整语法与陷阱)与隧道与端口转发(三种转发的方向语义与实战)。