公众号旧文
什么?本机 SSH 自己,还需要输密码?
刚刚我在跳板机上连一堆内网机器执行 find。远程机器一个个都很顺利,全部免密登录,结果偏偏第一台,也就是我自己,卡住了:
root@jp-iij:~# { echo root@127.0.0.1; cat hosts.txt; } | while read host; do
echo "===== $host ====="
ssh -n -o ConnectTimeout=5 -o StrictHostKeyChecking=no "$host" \
'find / -type f -name "IU-for-Domino-s-Pizza-documents-2.jpeg" 2>/dev/null'
done
===== root@127.0.0.1 =====
Warning: Permanently added '127.0.0.1' (ECDSA) to the list of known hosts.
root@127.0.0.1's password:
我当时第一反应是:这不科学啊?我 SSH 别的机器都不用密码,为什么 SSH 自己反而要输密码?
后来研究了一番才发现,原来这事一点都不离谱,甚至可以说是SSH 工作机制的一个经典错觉。
一、关键误区:本机 ≠ 已登录的会话
很多人(包括我一开始)会潜意识觉得:
我已经在这台机器上了,再 SSH 自己,不就是原地登录吗?
但事实是:
SSH 永远是一次全新的登录会话
无论你是:
- 连远程 IP
- 连
127.0.0.1 - 连自己的 hostname
对 SSH 来说,都是一样的流程:
- 建立 TCP 连接
- 走 SSH 协议握手
- 进行身份认证(关键点)
- 开启一个新的 shell 会话
也就是说你已经登录的状态,对 SSH 完全没有帮助。
二、免密登录的本质:不是“信任机器”,而是“信任密钥”
那为什么我连其他机器不用密码?
因为我之前做过这件事:
ssh-copy-id root@100.64.0.x
本质是:
- 本地有私钥:
~/.ssh/id_rsa - 远程有公钥:`~/.ssh/authorized_keys```
SSH 登录时流程是:
- 客户端说:“我有这个公钥对应的私钥”
- 服务端查
authorized_keys - 匹配成功 → 免密登录
三、问题的核心:你“以为配置了”,其实没配置
回到一开始的问题:
为什么 SSH 127.0.0.1 要密码?
答案通常是这几种情况:
1️⃣ 本机没有自己的公钥(最常见)
你可能做的是:
ssh-copy-id root@100.64.0.3
ssh-copy-id root@100.64.0.5
但你没有执行:
ssh-copy-id root@127.0.0.1
所以本机的 authorized_keys 里,压根没有你自己的 key。
2️⃣ SSH 走了不同的认证路径
比如:
- 远程机器允许 root + key 登录
- 本机
/etc/ssh/sshd_config限制更严格
常见配置:
PermitRootLogin prohibit-password
或者:
PubkeyAuthentication no
导致 key 根本没生效。
3️⃣ SSH 连接的“不是你以为的那个自己”
你用了:
ssh root@127.0.0.1
但也可能存在:
- hostname 解析不同
- IPv6 (
::1) 和 IPv4 (127.0.0.1) 配置不同 - sshd 监听策略不同
表面是“自己”,其实走的是另一套规则。
四、最优解:本机就别 SSH 自己
理解了原理之后,最佳实践其实很简单:
本机直接执行命令,远程才用 SSH
echo "===== LOCAL ====="
find / -type f -name "xxx" 2>/dev/null
while read host; do
ssh -n "$host" 'find ...'
done < hosts.txt
优点:
- 更快(少一次 SSH)
- 更稳定(无认证问题)
- 更干净(无 known_hosts 污染)
五、一个很有意思的类比
你可以把 SSH 想象成一栋大楼的门禁系统:
- 你在楼里(本机)
- 你刷卡进另一个房间(SSH)
门禁不会说:你已经在楼里了,不用刷卡了。
它只会看你有没有权限(密钥)。
你可能感兴趣的其他文章: