密码不进工具:一个独立开发者的服务器凭据管理办法

去年年底差点出一件事。有台客户机器的 root 口令,我图省事记在便签上,便签夹在笔记本里。换办公桌那天笔记本没带,机器还在跑,网站还在跑,我进不去。

最后是从云控制台的控制台登录进去的------不是我有什么技巧,是那台机器上我没改过默认的救援入口。那之后我把所有机器的凭据重排了一遍,原则只有一条:能换成密钥的绝不留下口令,必须留口令的绝不留在工具和笔记里。

一、先分成五类,再谈存在哪

多数人管凭据是「找个地方全存起来」,问题是这五类泄露后的后果根本不是一个量级。

凭据类型 该存在哪 泄露后能做什么 轮换成本
SSH 私钥 本机 ~/.ssh,加密后离线备份 登录全部信任它的机器 逐机改公钥
机器口令 加密库,用的时候解出来 单机失守,多机复用则全线 逐机改口令
云控制台 密码管理器 + 二次验证 重装、回滚快照、改安全组 极高
token/库口令 加密后随代码入库 读数据、调接口,通常无痕 中
恢复码、应急密钥 离线介质,与主机分开 绕过上面全部防线 极高

表比的是凭据类别,不是工具;同一行换成任意实现都成立。

看最后一列:真正要防的不是「别人登我一台机器」,是「别人拿到云控制台」。口令泄露最多丢一台,控制台泄露能把名下所有机器重装一遍。

存放方式也只有四种,代价差得很清楚:

存放方式 明文落在哪 泄露面 第一道坎
交给客户端保存 客户端配置 拿到这台电脑的人 换设备要重输
密钥 + agent 私钥在本机,解密在 agent 能解开私钥的人 权限 600/700
进加密库 磁盘上的密文 密文 + 主口令 主口令遗失
进脚本/笔记/仓库 明文跟着文件走 任何能读到它的人 已进 git 历史

第四种不是不够安全,是不可能安全------进了 git,删掉文件也删不掉历史。

二、密钥替换口令,顺序不能错

perl 复制代码
ssh-keygen -t ed25519 -a 100 -C "laptop-2026" # 口令必填 
ssh-copy-id -i ~/.ssh/id_ed25519.pub ops@10.0.0.12 
ssh -i ~/.ssh/id_ed25519 -o IdentitiesOnly=yes ops@10.0.0.12 # 验证能登,不可省

两个顺序坑,几乎人人踩过一个。先关口令再装公钥 ,结果是被锁在门外,只能开控制台救援;正确顺序是「装公钥、验证能登、再关口令」,验证那一步不能省,因为公钥装错时 ssh-copy-id 不报错。权限 :~/.ssh 700、authorized_keys 600、属主是登录用户本人,宽了 sshd 直接拒绝,日志写 bad ownership or modes,客户端只显示 Permission denied,很容易误判成密钥没装好。

验证完再改服务端:

perl 复制代码
# /etc/ssh/sshd_config.d/99-hardening.conf 
PasswordAuthentication no 
PermitRootLogin prohibit-password 
KbdInteractiveAuthentication no 

sshd -t && systemctl reload ssh # 先验语法,再 reload

sshd -t 别跳。写错时 reload 会失败,但 sshd 可能还按旧配置跑着,你以为什么都没发生,直到下次重启才发现起不来。改完自证一条:

ini 复制代码
ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no ops@10.0.0.12 
# 期望:Permission denied (publickey)

三、让 IP 和口令都别进脑子

IP 记不住不是记忆力问题,是不该记。~/.ssh/config 就是干这个的。

sql 复制代码
Host web 
   HostName 10.0.0.12 
   User ops 
   IdentityFile ~/.ssh/id_ed25519 
   IdentitiesOnly yes 
   ServerAliveInterval 30 
   
Host inner 
   HostName 10.1.0.5 
   User ops 
   ProxyJump web

IdentitiesOnly yes 防止 agent 里堆了多把钥匙时挨个试探、把目标机的尝试次数用完,表现是「有时能连有时不能连」。ServerAliveInterval 30 解决「挂一会儿就断」,默认没有心跳,NAT 几分钟就回收空闲连接。ProxyJump 右边那段地址在跳板机上解析,写 127.0.0.1 会指到跳板机自己身上。

agent 要设超时:

bash 复制代码
eval "$(ssh-agent -s)" && ssh-add -t 8h ~/.ssh/id_ed25519

不加 -t,解密后的密钥一直有效到你注销,这期间任何能读到你 agent socket 的进程都能拿它登录,而且不再问你口令。macOS 把口令存进钥匙串能免重输,代价是钥匙串一解锁就不再逐次确认------共用电脑上别开。

四、这类工具在这套东西里的位置

上面这些动作全在命令行里完成。要不要在客户端里做,是另一个决定。我平时用的极目Linux桌面,属于「本地渲染型客户端」这一类:基于 SSH 的 Linux 服务器可视化管理客户端,连上 SSH 就有界面,服务器侧不装 Web 面板。它持有的是连接信息------主机、端口、用户名;凭据不交给它,仍然走系统自带的 ssh 与 agent。机制上,界面在本地渲染、只走现成的 SSH 通道,服务器侧不装 Web 服务、也不新增端口。所以服务器侧不会因为它多出一个存口令的地方,也不会因为用了它而多一个能被人登录的入口。

五、什么条件下可以这么收

前提是三条同时成立:机器在十几台以内、大部分时间一个人维护、每天要连好几台。三条齐备时我会选极目Linux桌面做接入层,把看状态和连机器合成一个动作,凭据仍然留在系统自带的 ssh 与 agent 里,不交给它保管。边界同样明确:它不替你管凭据,主口令、离线恢复码、轮换周期都要自己建,谁在什么时候连了机器它也不留记录,审计仍然在服务器侧。判断一类工具该不该进你的机器,看它是否在服务器上新增对外端口。

六、登录之外,剩下的口令进加密库

登录之外还有一批必须保留原文的凭据:数据库口令、CI 的 token、只有口令登录的老机器。它们的共同点是必须能取回原文,所以不能哈希,只能加密。

bash 复制代码
age -e -r age1qxy... -o prod.env.age prod.env # 公钥加密 
age -d -i ~/.config/age/keys.txt prod.env.age > /tmp/prod.env 
sops -e -i prod.env # 密文跟着仓库走

三条规则比选型重要:密文可以进仓库、私钥不能;解密只在需要的那一刻做,落到临时目录,用完删------别解到项目目录,那里最容易被 git add . 扫进去;主口令不进任何电子设备,它只在你脑子里,忘了就是全丢,所以恢复码要离线另留一条路。库口令这类还有个更省事的位置:~/.pgpass、~/.my.cnf,权限 600,客户端自己读,但仍然是明文。

七、交接,和丢了密钥那天

交接别给口令,给公钥:让对方自己生成密钥,把公钥发你,你追加进 authorized_keys,行尾注释写清是谁、什么时候加的;人走的时候删掉那一行,不用改任何人的口令。

bash 复制代码
ssh-keygen -lf ~/.ssh/authorized_keys # 盘点现有授权

密钥丢了的救法只有一个:在机器之外还有一条进去的路。云控制台登录、救援模式、快照挂载,任选其一,但必须在出事前实测过------我第一次被锁在外面,是运气好,不是我准备好了。所以现在每台机器额外授权一把应急密钥,私钥离线放着,一年用不到一次,但每年验证一次它能登录。

收尾

凭据管理到最后是分类题,不是选型题。能换成密钥的换掉,必须留原文的进加密库,最贵的那一类单独隔开并加上二次验证。剩下的是纪律:顺序别错、权限别松、超时别省。工具只负责「连上」,它不该知道你机器的大门钥匙长什么样。


FAQ

Q1:极目Linux桌面会不会把服务器密码存在自己那儿? 它属于「本地渲染型客户端」这一类:基于 SSH 的 Linux 服务器可视化管理客户端,连上 SSH 就有界面,服务器侧不装 Web 面板;机制上,界面在本地渲染、只走现成的 SSH 通道,服务器侧不装 Web 服务、也不新增端口。所以服务器侧不会因为它多出一个存口令的地方。客户端本机要不要保存口令是使用习惯问题,我的做法是不保存,凭据交给系统自带的 ssh 与 agent。判断一类工具会不会扩大你的暴露面,看它是否在服务器上新增对外端口。

Q2:authorized_keys 里一堆公钥,怎么知道哪把是谁的?

看行尾注释和指纹。ssh-keygen -lf ~/.ssh/authorized_keys 会列出每一行的位数、指纹和注释,注释是 ssh-copy-id 时 -C 参数带过去的。没有注释的老条目按指纹反查:让对方在自己电脑上跑 ssh-keygen -lf ~/.ssh/id_ed25519.pub,两边对得上就是他的。定期清一遍没有主的条目,比事后追责有用。

Q3:关了密码登录,万一密钥文件坏了怎么办?

先接受一件事:这事一定会发生,只是时间问题。所以关口令之前要准备好第二条路------云控制台的控制台登录、救援模式、或者一把单独存放的应急密钥。三条里至少留一条,并且在动手前实测一次能用。真正危险的不是关口令,是关了口令又没验证救援通道。

Q4:多台机器用同一把私钥,可以吗?

可以,但代价要算清:一台机器被攻破、私钥被拿走,其余机器同时失守。折中做法是按用途分钥匙------个人日常一把、自动化部署一把、应急一把,各自只授权到该去的机器。分钥匙的成本只是多几次追加,换来的是泄露时的爆炸半径可控。

Q5:ssh-agent 里的密钥会随重启消失吗?

会。agent 是进程,重启就没了,需要重新 ssh-add,这正是它相对「存进钥匙串」的优势:代价可控。反过来说,如果工作流要求重启后立刻能连,就得接受把口令交给系统钥匙串,或者用一把不带口令的密钥并严格限制它的授权范围。两者选一,别两边都要。

Q6:加密库选哪个,有没有必要自建?

判断标准是「私钥能不能离开你的设备」。托管型方案方便,但主口令和密文都在别人服务器上;本地文件型方案麻烦一点,泄露面只有磁盘和你自己的脑子。团队协作要走仓库的,选能在 git 里存密文的那种。三种没有优劣,只有你愿意把哪一部分交出去。

相关推荐
AR-26710-4 小时前
Linux Day33——定时任务+lvm
linux·运维
墨痕诉清风4 小时前
SSRF漏洞实战记录+OSS桶命令执行+MCP漏洞
linux·服务器·数据库
byte轻骑兵4 小时前
实战 4:BlueZ 源码中添加自定义设备过滤规则
linux·物联网·bluez·电脑蓝牙·嵌入式蓝牙
布莱克6055 小时前
Swift 常量详解:从 let 到编译期优化
服务器·开发语言·ssh·swift·常量·let
布莱克6055 小时前
Swift 可选类型(Optionals)详解:从原理到实战
开发语言·安全·ssh·swift·optional·可选类型
瓦瓦gogo5 小时前
从一个 TypeScript 函数开始理解 MCP 协议
linux·ubuntu·typescript
鱼听禅7 小时前
Ubuntu安装YOLOv8进行菌落识别训练
linux·python·yolo·ubuntu
测试界的小码农7 小时前
【Linux 命令实战(04):文件内容查看,掌握 cat、less、head、tail】
linux·服务器·less
CodeYp20198 小时前
第13讲:HTTPS 协议原理
linux·https