目录:SSH 是两套独立系统#
OpenSSH 同时扮演客户端(ssh)和服务器(sshd),同一套软件中的不同程序读取各自配置:
| 方向 | 程序 | 目录 | 归属 |
|---|---|---|---|
| 出站(你连别人) | ssh 客户端 |
~/.ssh/ + /etc/ssh/ssh_config |
你(用户级) |
| 入站(别人连你) | sshd 服务器 |
/etc/ssh/ + 每用户 authorized_keys |
系统 + 用户 |
SSH 出站(你是客户端):
你 ──ssh──▶ GitHub
~/.ssh/ ← 你的通行证、偏好、信任名单
SSH 入站(你是服务器):
Windows ──ssh──▶ 你
/etc/ssh/ ← 服务器运行配置 + 系统户口本
~/.ssh/authorized_keys ← 你放行的客人名单四类认证材料各管一块#
在常见的公钥认证连接中,可以区分四类材料;authorized_keys 与 known_hosts 是列表文件,并非各自一把密钥:
| Key | 位置 | 回答的问题 | 谁验证谁 |
|---|---|---|---|
| id_ed25519(你的私钥) | ~/.ssh/ |
你是谁 | 对端验证你 |
| authorized_keys(别人的公钥) | ~/.ssh/ |
谁被授权进来 | 你验证对端 |
| host key(系统私钥 + .pub) | /etc/ssh/ |
我是哪台机器 | 对端验证你 |
| known_hosts(对端主机公钥或 CA 等信任记录) | ~/.ssh/ |
我信任哪些服务器 | 你验证对端 |
authorized_keys 的例外归属
authorized_keys在~/.ssh/里,但它是入站用的——它是「服务器允许谁进来」的名单,按用户存放。本质是 sshd 读的配置,只是放在各用户家目录方便自管。
公钥不会自动登记 客户端验证服务端 host key;使用公钥认证时,服务端验证用户私钥的签名。管理员需预先把用户公钥加入目标账户的
authorized_keys(或使用证书/其他授权机制);连接不会自动把来访用户公钥加入授权名单。客户端接受或预置信任后才记录服务器公钥。用户也可通过密码等方式认证,不是每种连接都使用用户公钥。
双向认证:为什么需要 host key#
SSH 连接不只是验证「你是谁」,而是双向验证:
desktop ──────SSH 连接──────▶ 你的机器
方向1(验证对端身份):
对端出示自己的私钥签名
你的机器用 ~/.ssh/authorized_keys 里的公钥验证
方向2(验证你的机器 = host key 的活):
你的机器出示 host key 私钥签名
对端用 known_hosts 中已信任的主机公钥验证host key 干的是方向 2——它是你的机器反向证明「我是我」的身份证。 这也是上面那个 A/B 机器例子说的「双方互相确认对方身份」。
为什么需要反向验证(防中间人):
desktop ──▶ [攻击者假装是你] ──▶ 真的你
↑
desktop 以为连的是你,其实连的是骗子攻击者先连到你,再伪装成你接受 desktop 的连接。desktop 输入的凭据交给了攻击者。host key 防的就是这个:desktop 第一次连接时记下你的指纹,之后每次校验「指纹还对不对」。
TOFU 模型的本质与局限#
TOFU(Trust On First Use,首次使用即信任):
- 第一次连接:核对并接受对端 host key,把主机公钥记录到 known_hosts
- 之后每次:校验「还是不是那个指纹」
它解决什么(连续性):
场景A(TOFU 能防):你在 A 网吧连真 GitHub,记下真指纹;
之后在 B 网吧,攻击者冒充 GitHub → 指纹对不上 → 警觉 ✓它解决不了什么(首次真实性):
场景B(TOFU 防不了):你第一次就连上假 GitHub → 记下假指纹 → 永远被骗 ✗TOFU 的盲区 TOFU 只能保证「之后连的还是不是第一次连的那个」,不能保证「第一次连的那个是不是真的」。如果第一次就连上骗子,指纹验证等于摆设。
首次信任怎么补强:带外验证#
- 查官方公布的指纹:GitHub、云厂商官网公开自己的 host key 指纹,连接后
ssh-keygen -lf对比 - SSH 证书(SSH CA):大公司给每台服务器签发证书,客户端预置 CA 公钥,首次连接也可验证
- 私有网络/直连:可减少暴露面,但同一局域网也不能单独证明身份;最好仍从服务器控制台或可信渠道取得指纹核对
TOFU 适合能够接受首次信任风险的场景;公开指纹、可信控制台或预置信任材料可加强首次验证。不要为消除提示全局关闭 host key 校验。
GitHub 的 git 入口与账户识别#
连 GitHub 时 User git 是统一入口名,不代表你的 GitHub 账户名。GitHub 靠公钥识别账号,不看用户名。多账号靠「同一个 git + 不同 IdentityFile」区分:
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/id_work # 工作账号的 key通用目录示例#
~/.ssh/
├── id_ed25519 # 用户私钥,应设置 passphrase
├── id_ed25519.pub # 用户公钥,注释可写 user@workstation
├── authorized_keys # 允许登录此账户的用户公钥
├── known_hosts # 已信任的服务器主机公钥
└── config # 用户客户端配置
/etc/ssh/
├── ssh_config # 系统级客户端配置
├── sshd_config # 服务器配置
└── ssh_host_ed25519_key # 服务器主机私钥关键洞察#
目录归属的本质是「谁拥有这份配置」——/etc/ssh/ 是系统所有(机器身份,root 管),~/.ssh/ 是用户所有(你的身份,你管)。authorized_keys 卡在中间:既是服务器的授权逻辑,又按用户的客人名单分,所以它在 ~/.ssh/ 但归入站用。
相关#
- agent 与密钥保护 → ssh-agent、passphrase 与 keyring
- 命令行操作 → SSH 使用指南
参考与延伸
根据技术笔记重新整理,示例使用通用名称。