Skip to content

加密技术 ​

加密技术是信息安全的核心,用于保护数据的机密性和完整性。但"加密"两个字在 Linux 运维里其实指向四件不同的事:保护传输(TLS/SSH)、证明身份与完整性(GPG 签名)、保护静态数据(LUKS 磁盘加密)、校验一致性(哈希)。分不清这四件事,就会用错工具——比如试图用哈希"加密"文件、或把自签名证书当成公网可信证书。本篇按"为什么需要这种加密 → 怎么落地"展开,覆盖三系工具安装与常见事故。

内容参考自 OpenSSL、GnuPG、OpenSSH、cryptsetup 官方文档与 Arch Wiki,见文末参考资料。

导语 ​

安全问题里有一半最终会落到"数据在某个环节变得不安全":数据库导出文件被人拷走、SSH 靠弱口令被登录、下载的安装包被中间人替换成后门、旧硬盘退役后直接送人。加密是应对这些场景的通用语言,但它不是一锤子买卖——选错密钥类型、搞错证书链、忽略恢复手段,加密会带来比不加密更糟的后果(数据永久无法解密、信任链被错误信任污染)。

Linux 生态里这四件事各有成熟工具且几乎全部预装或官方仓库可得:openssl 三系都有,GPG 在 Debian/Arch 是 gnupg、RHEL 系是 gnupg2,SSH 用 openssh,磁盘加密是 cryptsetup。Arch 上一句 sudo pacman -S gnupg cryptsetup 就能把缺的补齐(sudo pacman -S openssl openssh 同理补齐传输侧),其余多数字节在最小安装里已经躺在 /usr/bin 下。工具齐全只是起点——同一台机器上这四件事的配置质量可能天差地别:默认 SSH、过期证书、未签名的部署脚本、没备份头的加密盘,全都是"装了工具但没建立纪律"的典型状态。本篇每节都按"工具安装 → 威胁模型 → 操作纪律"展开,命令是表,纪律才是里。

学习目标 ​

  • 说清对称与非对称加密的分工,理解为什么真实协议(TLS、SSH)两者都要用
  • 掌握哈希的用途边界:能校验完整性,不能用来"加密还原"
  • 会用 GPG 生成密钥、签名与验签,理解 Web of Trust 的信任模型
  • 看懂 TLS 握手与证书链,能用 openssl 检查证书有效期与链路
  • 用 SSH 密钥(ed25519)替代口令登录,避开私钥保护与 agent 的常见坑
  • 理解 LUKS 全盘加密的适用场景与不可逆风险

六条目标对应本篇六个正文章节(1 节打底,2–5 节分工具,6 节收坑)。建议的读法是先通读第 1 节建立原语直觉,再按你手头最紧急的场景跳读——比如正在做发布流程就直奔 GPG,正在收 SSH 就看第 4 节;但不要跳过第 1 节,后面所有"为什么不能用 X 做 Y"的判断都建立在那张原语表上。每条目标都配了文中的可回读动作(gpg --verify 看签名者、openssl 看 notAfter、sshd -T 看生效配置),检验时以命令输出为准,不以"我读过了"为准。六条还可以压成一句选型口诀:先问属性(机密/完整/身份),再选原语,最后才开工具——顺序反了就会出现"哈希当加密"这类执行成功、保护为零的假动作。

学习目标里第 4、5 条共享同一条底层纪律:不可逆操作之前,先验证替代通道存在——关口令前先确认密钥登录,luksFormat 前先确认设备名与头文件备份位置。第 2、3、6 条则共享另一条:以可回读的命令输出为准——签名者列表、notAfter 字段、sshd -T 生效值,都是能写进变更单的证据。把六条按这两条纪律分组,比按章节顺序背更容易在实战时调用出来。两条纪律还可以再合成一句给值班用的话:动密钥之前先留后路,动完之后先看输出——加密类变更的大多数事故,都能追溯到这两句里的某一句没执行。

学完的操作性检验:给定一个发布物、一台新服务器、一块移动硬盘,你应该能分别完成"签名+验签""ed25519 密钥登录并关口令(确认新通道可用后)""LUKS 格式化+头文件备份+测试解锁"三件事,并对每一步说出它防的是谁。三件里任何一件说不清威胁对象,说明只是在敲命令,还没建立威胁模型。检验里两处"确认后再做"的顺序不能换——签名后先在另一台机器验签、密钥登录后先新开会话再关口令——把顺序做对,比把命令敲快更能证明你理解了风险边界。

威胁模型的口头检验还可以再加一问:这三件事分别在什么情况下会失效? 签名防不了私钥被盗后冒名签发,密钥登录防不了攻击者先植入木马读你的 agent,LUKS 防不了机器解锁后被直接读盘——能主动说出失效条件,说明威胁模型是完整的;只会说"做了就安全",说明还停留在工具层。

1. 加密基础:三类原语各解决什么问题 ​

工具手册总是从"怎么生成密钥"讲起,但运维选型的顺序应该反过来:先问要保护什么属性,再选原语,最后才落到命令。把顺序搞反的典型症状是"用 AES 加密了密码哈希"或"给文件做了 SHA-256 就宣称已加密"——命令都执行成功了,属性却完全没被保护。运维口中的"加密"其实是三套完全不同的数学原语在干活。选型时先问要保护的属性是什么:机密性(别人看不到)找对称或非对称加密;完整性/身份(别人改不了、且能证明是谁改的)找签名与哈希;两者常常组合出现,但工具与命令完全不同。用错原语的代价不只是"没效果"——哈希当加密用会给人虚假的安全感,签名漏验则等于没有签名。也可以把三行表读成"三个不同的问题句":"别人看得到吗"→ 加密,"别人改了吗/这是谁发的"→ 哈希+签名,"密钥怎么安全地送到对方手里"→ 非对称——先写问题再选工具,是本篇全篇的选型纪律:

原语用途典型算法关键特征
对称加密大批量数据的机密性AES-256-GCM、ChaCha20加解密同一把密钥,快
非对称加密密钥交换、数字签名Ed25519、RSA、X25519公钥/私钥成对,慢
哈希函数完整性、指纹SHA-256、SHA-512单向、定长、不可还原

1.1 为什么对称与非对称都要有 ​

对称加密的困境是密钥分发:你和对方要共享同一把密钥,那这把密钥怎么送到对方手里而不被窃听?——用来保护"送密钥过程"的,正是非对称加密。非对称的困境是性能:公钥运算比 AES 慢几个数量级,不适合加密整块磁盘或整段视频流。

于是所有现代协议都采用混合模式,TLS 是最典型的例子:

  1. 握手阶段用非对称算法完成身份验证与会话密钥协商(客户端验证服务器证书签名,协商出一把一次性对称密钥);
  2. 应用数据阶段全部用这把对称密钥加密(AES-GCM 等)。

SSH 同理:密钥交换用 KEX(基于椭圆曲线/DH),一旦通道建立,后续数据走对称加密。记住这个分工:"非对称解决第一次见面怎么互信,对称解决见面之后怎么高效说话"。

这个分工也解释了运维里的两个常见现象。其一,TLS 证书"太大太重"的抱怨多半来自握手阶段的非对称运算与证书链传输,HTTP/2、会话复用、TLS 1.3 的 0-RTT 都是在压缩"第一次见面"的成本,而非替换掉非对称这一步——没有公钥体系,双方无法在公开信道上协商出一把只有彼此知道的密钥。其二,SSH 每次登录都要经历 KEX,但之后传输大文件很快,因为真正搬数据的是对称密码。理解这两层结构,再看"为什么不能纯用 AES"或"为什么 RSA 慢"这类问题,答案就自然落在了正确的层上。

选型落到算法名上,可以先背一组"默认就够用"的现代组合:TLS 侧看 TLS 1.3 或 1.2 + AEAD 套件(AES-GCM、ChaCha20-Poly1305),SSH 侧密钥用 ed25519、KEX 用 curve25519 系,证书签名用 ECDSA P-256 或 RSA-3072+。老教程里的 3DES、RC4、SHA-1、TLS 1.0/1.1 出现在配置里就应当视为待清理项——算法清单会过期,但"默认用现代、显式禁用老套件"这条策略不过期,三系的发行版默认配置近年都在朝这个方向收紧,自定义配置时对齐发行版默认往往比抄五年网文更安全。

1.2 哈希不是加密 ​

表里最后一行最容易被误用,值得单独展开:哈希是单向的——sha256sum 无法"解密"回原文,因此它不提供机密性,只提供完整性与指纹。常见误用是"我把密码 MD5 存起来了所以安全"——MD5/SHA-1 已被碰撞攻击攻破,密码存储要用 bcrypt/scrypt/Argon2 这类刻意变慢的 KDF,不是普通哈希。日常校验文件完整性用 SHA-256 即可:

bash
$ sha256sum backup.tar.gz
e3b0c442...7852b855  backup.tar.gz

Linux 发行版的软件仓库签名、ISO 下载校验,全部建立在"哈希 + 非对称签名"的组合上:仓库用私钥对"包哈希清单"签名,客户端用公钥验证——这正是下一节 GPG 的主战场,也是 pacman、apt、dnf 能"自动信任官方源"的数学基础。你在安装软件时看到的"检查签名"提示,背后就是这套机制在替你做信任决策;它安全的前提是系统信任库里那把仓库公钥没有被替换——根信任一旦失守,整条链自动验签通过也没意义。这也是为什么基线加固(见安全加固)要保护 /etc/pacman.d/、/etc/apt/ 这类信任锚点目录的写权限。

2. GPG:签名、加密与信任链 ​

前面反复强调"哈希 + 签名"的组合,落到工具上就是 GPG(GnuPG)——OpenPGP 标准的实现,运维场景里最常用的是签名(证明"这个文件确实是我发布的")而非加密。把签名排在加密前面不是笔误:多数团队一年也用不上一次 GPG 加密通信,却几乎每周都要给发布物、配置变更或备份清单签个名;投入产出比一目了然。也可以说,签名回答的是"这东西能不能信",加密回答的是"谁能看到"——运维日常里前者的出现频率压倒性更高,所以本节主线从签名切入,加密只在威胁模型明确要求时才启用。三系安装:

bash
# Debian/Ubuntu
sudo apt install gnupg
# Arch
sudo pacman -S gnupg
# RHEL/CentOS/Rocky
sudo dnf install gnupg2

注意 RHEL 系包名是 gnupg2,但提供的仍是 gpg 命令——包名与命令名不一致是新手搜教程时的常见困惑。装完用 command -v gpg 确认,而不是假定包名等于命令名;三系的 gpg 行为基本一致,密钥环目录默认都在 ~/.gnupg/,跨发行版迁移密钥时直接拷贝该目录(注意属主与权限)即可。

迁移密钥环还有一个安全细节常被忽略:拷贝 .gnupg 等于拷贝全部私钥,传输通道本身必须是加密的(scp/ssh,不要走普通 HTTP 网盘),目标机上先 chmod 700 ~/.gnupg 再放入文件,避免中间态被同机其它用户读到。服务账号场景(CI 流水线要签名)不建议复用个人密钥环,应单独生成一把用途受限的签名密钥并限制其信任级别——个人身份密钥与机器身份密钥混用,是泄露半径最大的一种偷懒。

GPG 在运维场景里的优先级排序值得明确:签名 > 加密 > 密钥管理。绝大多数团队真正需要的是"发布物带签名、消费方会验签";GPG 邮件加密、公钥分发网络(WKD)这类完整 OpenPGP 社交模型在企业内部很少落地——把时间花在把 --detach-sign 接进发布流水线,比研究 Web of Trust 的六级信任更划算。信任模型本身也可以按运维视角简化成一句话:你只需要认识"团队发布钥"这一把,并把它钉进配置管理;其余 Web of Trust 的转签网络在内网场景几乎用不上,别为它设计流程。

2.1 生成密钥对 ​

密钥对是后面所有签名、验签动作的身份根基——先有可信的密钥,才有可信的签名,这一步的算法选择与过期策略会一直影响到流水线里的每一次 --verify。生成阶段少做的两个决定(算法、过期时间),往往在两年后的"密钥轮换危机"里被成倍索取——所以这一步值得放慢。生成动作本身一分钟能完成,围绕它的三个决定(谁是 uid、何时过期、公钥怎么分发)却会决定这把钥匙在整个团队里的生命周期——把决定写进密钥登记表,比事后翻聊天记录可靠。新版 GPG 推荐交互式完整生成(可指定算法与过期时间),而不是无脑回车:

bash
$ gpg --full-generate-key
Your selection? 9          # ECC:Curve25519 现代默认

生成后查看与导出:

bash
$ gpg --list-secret-keys
sec   ed25519 2026-09-22 [SC] [expires: 2027-09-22]
uid  [ultimate] Ops Admin <ops@example.com>
$ gpg --export -a "Ops Admin" > ops-public.asc          # 公钥可分发
$ gpg --export-secret-keys -a "Ops Admin" > ops-private.asc  # 私钥=高危

[ultimate] 信任级别说明这是你自己的密钥。算法选择上,现代 GPG 默认/推荐 ECC(Curve25519):签名短、验证快,与 SSH ed25519 同源思路;需要兼容老版本 GnuPG 或某些 HSM 场景才回退 RSA 3072+。密钥过期时间不要设成"永不过期"——过期是一种主动的生命周期管理:到期强制轮换,比十年不换的"长期密钥"更安全,也逼着团队处理密钥更换流程。

私钥导出文件等同于身份本身——放到代码仓库、贴到聊天工具、和备份混放,都等于把身份送人。正确做法是导出后立即加密存储(至少再套一层 passphrase 或放进加密卷),并用 gpg --delete-secret-keys 清掉临时副本。导出前后建议 ls -l ~/.gnupg/ 看一眼权限(应为 700),私钥材料的权限错误与私钥泄露只有一线之隔。

2.2 签名与验签(运维最高频用法) ​

发布脚本、配置或软件包时,对文件的哈希做非对称签名,接收方用你的公钥验签。签名把第 1 节的哈希与非对称组合起来:哈希给出"内容指纹",私钥签名给出"指纹的归属"——接收方只需持有你的公钥,就能同时验证"没被改过"和"确实出自你"。这也是为什么分发公钥(钉进配置仓库或发行版元数据)比分发公钥本身更重要:验签失败时,先确认信任根,再怀疑文件。

bash
$ gpg --detach-sign deploy.sh
$ gpg --verify deploy.sh.sig deploy.sh
gpg: Good signature from "Ops Admin <ops@example.com>" [ultimate]

验签输出要盯住的是 Good signature 和签名者身份——如果显示的是你不认识的 key,或提示 BAD signature,文件已被篡改或签名不匹配,立即停止使用。这里有个容易被脚本化的陷阱:gpg --verify 的退出码在"签名有效但签名者不在信任环"时也可能为 0,自动化流水线必须解析输出中的 key ID 与 Good signature,不能只看 $?。gpg --verify 只校验签名有效性,不等于你信任这个签名者;信任与否取决于你是否把对方公钥导入并给了信任级别:

bash
$ gpg --import ops-public.asc
$ gpg --edit-key 9A3F21B0C4D5E6F7890123456789ABCDEF012345  # trust → 3(完全信任)

签名流程接进 CI/CD 时还有两个工程细节。其一,签名密钥不要进代码仓库或明文 CI 变量:用密钥管理服务(Vault、云 KMS、受保护的 runner secret)注入,流水线结束后即消失;一旦私钥进了 git 历史,唯一正确动作是作废旧钥并全员换信任,而不是 git rm 了事。其二,验签步骤要失败即停:把 gpg --verify 放在部署脚本的第一行、后面所有解压与执行都在它之后,顺序反了等于验给已经执行过的代码看——这与防火墙"先放行再启用"是同一类顺序纪律,只是这里拦的是供应链而不是网络包。

加密/解密(对称与非对称)日常也有用,但注意 GPG 的对称加密(gpg -c)密码一旦忘记无法找回,这与 LUKS 见第 5 节的提醒是同一条纪律。

3. TLS 与证书:HTTPS 背后的信任链 ​

3.1 握手在做什么 ​

看到"TLS 握手"就想到 Wireshark 抓包的人,往往会低估它在运维侧的分量:握手不只是协议课本里的五步时序,更是证书、密码套件、客户端信任库三者交汇的现场——握手失败的报错几乎总能追溯到其中一项配置错误。HTTPS = HTTP over TLS。握手阶段完成三件事:协商密码套件、验证服务器身份(证书链)、派生会话密钥。简化时序:

  1. 客户端给出支持的 TLS 版本与算法列表;
  2. 服务器返回证书(含公钥与 CA 签名);
  3. 客户端用内置 CA 根证书验证签名链,确认域名匹配、有效期未过;
  4. 双方(ECDHE 场景)交换参数派生出对称会话密钥;
  5. 后续应用数据全用该密钥加密,并用 AEAD 的认证标签防篡改。

理解"客户端为什么信任服务器"的关键在第 3 步:信任来自根 CA 在你系统信任库里存在(三系都由 ca-certificates 包维护),不是来自证书本身有多"正式"。自签名证书在数学上同样正确,只是没人替它背书,浏览器/客户端会警告。信任库的运维含义有两层:其一,系统升级会更新内置根 CA 列表,你自签或自建 CA 的服务在部分客户端上仍要手动导入根证书;其二,谁控制了信任库写入权,谁就能让任意证书"变可信"——恶意软件篡改 ca-certificates 是经典手法,这正是 AIDE 把 /etc/ssl/certs 纳入监控的理由之一。

3.2 用 openssl 检查证书 ​

证书排查是运维高频动作——"站点打不开了""客户端报不受信任""是不是被劫持了"最终往往都落到这几条命令上。三条命令覆盖 90% 场景:

bash
# 看有效期、颁发者、主题
$ openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
    | openssl x509 -noout -dates -issuer -subject
notAfter=Sep 29 23:59:59 2026 GMT
issuer=C = US, O = Let's Encrypt, CN = R11

# 看完整证书链(排查"中间证书缺失")
openssl s_client -connect example.com:443 -showcerts </dev/null
# 验证链是否被系统信任
openssl s_client -connect example.com:443 -verify_return_error </dev/null

notAfter 到期是最常见的生产事故之一:证书过期 = 站点不可访问,且客户端不会"自动续期"。把"剩余天数"做成监控指标比依赖续期脚本本身更可靠——续期进程静默失败、reload 钩子没触发、多台机器上有一台漏了,这些都会在到期日集中爆发。自动化证书(如 certbot / ACME 客户端)要配好续期后的 reload 钩子——很多"续期成功但站点仍报错"的事故,根因只是 Nginx 没 reload 到新证书。

监控"剩余天数"的具体做法可以很轻:一条 cron 每天跑 openssl s_client 取 notAfter,算出天数推给告警通道,阈值设 30/14/7 天三档。它与续期脚本的健康监控是两回事——脚本监控告诉你"任务跑了",天数监控告诉你"证书还有效",后者才是业务真正关心的量。多台机器、多个域名时,把清单(域名:端口)放一个文本文件循环检查即可,不需要引入重量级证书管理系统,除非已经管理到几十张证书的规模。

证书链排查也有一条经验路径:先 -showcerts 看服务端是否只发了叶子证书(中间证书缺失是自建 CA/错误配置的高发病),再 -verify_return_error 看系统信任库是否接受整条链,最后核对 -dates。三步能定位绝大多数"浏览器报不受信任、curl 却正常"或"部分客户端失败"的链路问题——不同客户端的中间证书缓存(AIA fetching)能力不同,服务端发全链是最省事的互通性修复。

自签名证书仅用于内网实验或服务间 mTLS,生成时注意算法与有效期:

bash
$ openssl req -x509 -newkey rsa:3072 -nodes -days 365 \
    -keyout server.key -out server.crt -subj "/CN=server.internal"

私钥 server.key 权限必须是 600 且属主为服务账号——openssl 不会阻止你把私钥设成全局可读,这是权限层面的事,见安全加固。自签与公网 CA 证书的分工也值得再强调一次:自签适合服务间 mTLS、内网实验、无法联网的环境;面向公网浏览器的站点必须用受信任 CA 签发的证书,否则每个用户都会看到警告,安全提示最终会被训练成"点继续"的肌肉记忆——用警告消耗用户警惕,是比证书本身过期更隐蔽的长期风险。

证书运维的三件套(生成、续期、告警)里,新手最容易只做第一件:openssl req 生成一张一年期证书贴上去,然后靠记忆续期。正确的形态是把"到期前 30 天告警"写进监控、把"续期后 reload"写进钩子、把"链是否完整"写进上线检查——三件缺一,证书都会在某个深夜以最难排查的方式坏掉。自签场景虽然不走 ACME,同样建议给证书文件设到期提醒,内网服务因证书过期而中断时,浏览器上的"不安全"警告反而会让人误以为是攻击,排查方向先错一步。

4. SSH 密钥:用非对称替代口令 ​

把第 1 节的"非对称解决第一次见面"直接落到日常:SSH 是非对称加密在运维中最日常的落点——服务器持有公钥(authorized_keys),你持有私钥,握手后建立加密通道并完成身份认证。相比口令登录,密钥登录同时解决抗爆破(256 位随机私钥无法被字典攻击)与自动化(脚本免交互)两个问题。口令登录面对的是"每秒几十次的在线猜测",密钥登录面对的是"2^256 的离线穷举"——两者不是一个量级的战场,这也是几乎所有安全基线都把 PasswordAuthentication no 列为必选项的原因。也可以把两者比作门锁:口令是可被撬开反复试的弹子锁,密钥是每次尝试都物理上不可枚举的量子随机码——换锁不是加固旧锁,是换掉威胁模型。

密钥方案选型在今天几乎没有争议:新环境一律 ed25519——密钥短、签名快、实现简单,与 GPG 的 ECC 推荐同源;需要兼容极老的路由器/交换机固件时才回退 rsa + 3072 位以上。不要再生成 2048 位 RSA 作为新标准,老教程的默认值已经落后于当前的强度基线;反过来,也不要为了"更新"去用尚无广泛支持的新兴曲线——运维密钥的第一属性是互操作,第二属性才是数学上的时髦。选型还可以记一条对照:SSH 密钥与 GPG 密钥在算法选择上应保持同一世代(都用 ed25519),这样团队心智模型、密钥管理脚本、审计清单都能共用一套,而不是两套各写各的。

从部署成本看,密钥切换是加密改造里投入产出比最高的一项:不需要 CA、不需要改业务代码、不需要申请域名,三条命令就能完成。真正拖慢团队的从来不是 ssh-keygen,而是切换流程没设计好——谁的密钥先发、旧口令什么时候关、临时外协怎么办。把这三问答清楚再动手,比纠结用 ed25519 还是 RSA 3072 更重要(答案是:新环境一律 ed25519,回退 RSA 只为兼容不支持它的老设备)。

bash
$ ssh-keygen -t ed25519 -C "ops@$(hostname)"
$ ssh-copy-id user@server
$ ssh -o PreferredAuthentications=publickey user@server "echo ok"
ok

公钥(.pub)可以公开,私钥(无后缀)必须 chmod 600。私钥建议再加口令短语(passphrase)并用 ssh-agent 记住,兼顾"丢了备份也不至于裸奔"与"日常免输 passphrase"。没有 passphrase 的私钥一旦被拷走就是永久的后门,直到你发现并轮换 authorized_keys——加了 passphrase 则至少多出"需要同时拿到私钥文件 + 记住口令"两道门槛。agent 本身的边界也要清楚:ssh-agent 把解密后的私钥留在内存里供签名,因此在共享主机或已失陷机器上跑 agent 风险很高(同机有权限的进程可能通过 agent socket 代理登录);高风险环境用 ssh-add -c 让每次使用需确认,或干脆不驻留 agent。密钥生命周期里还有一步常被省略:人员离职/岗位调动时的撤销——authorized_keys 不像口令那样有全局"改一次全失效"的开关,每台机器都要删,用配置管理批量下发才能保证不漏;这也是把公钥纳入资产清单(谁的、发给哪几台、何时发的)的实际理由。

bash
$ eval "$(ssh-agent -s)"
$ ssh-add ~/.ssh/id_ed25519
Enter passphrase for /home/cui/.ssh/id_ed25519:

服务器侧配套加固(完整清单见安全加固):PasswordAuthentication no、PermitRootLogin no、PubkeyAuthentication yes。顺序上必须先确认密钥登录成功,再关口令——先关口令后配密钥,把自己锁在门外的经典剧本与防火墙"先 enable 后 allow"是同一类错误。三系的 sshd 单元名不同(Debian 是 ssh.service,Arch/RHEL 是 sshd.service),改完配置用 sshd -t 语法检查再重启,细节见加固篇。

密钥登录切换完成后,还有一项收尾容易漏:把旧口令时代的残留清干净——/home/*/.ssh/authorized_keys 里过期的键、临时加过的 PermitRootLogin yes、为方便测试开过的 PasswordAuthentication yes 备份文件,都应在切换窗口一并回收。验证方式是再跑一次 sshd -T | grep -iE 'passwordauth|permitroot',确认生效值而不是文件里写了什么;文件与生效值不一致时(drop-in 覆盖、Match 块),以 sshd -T 为准——这也是排查"明明关了还能口令登录"的第一入口。

authorized_keys 的权限与属主也是高频故障点:文件属主必须是登录用户本人、权限 600,~/.ssh 目录 700——sshd 出于安全考虑会拒绝权限过宽的密钥文件,症状是"公钥明明贴上去了还让输口令"。排查时先 ls -la ~/.ssh 再看 sshd -T 的实际生效配置,比反复重装密钥快得多。密钥分发优先用 ssh-copy-id,它会自动处理追加与权限;手工 cat >> 是权限事故的主要来源。

5. 磁盘加密(LUKS):静态数据的最后一道闸 ​

传输中的数据有 TLS,文件级有 GPG,最后剩下一个常被忽略的缺口:磁盘本身——数据写进扇区后就静默躺在那里,直到硬盘被拆走、被送修、被旧货市场转卖。LUKS 补的就是这个"静态数据"的洞,它是本篇四条主线里唯一直接对着硬件失窃场景设计的。也可以按"数据在哪"重述四条主线:在链路上走的是 TLS,在发布物里的是 GPG,在登录会话里的是 SSH 密钥,在断电后仍躺在介质上的,只有 LUKS 能管。这四条主线的运维节奏也不一样:TLS/SSH 配一次就长期有效,GPG 随发布节奏使用,LUKS 则在创建时定终身(密钥槽、passphrase、头文件备份都在 luksFormat 那一刻决定大半)。理解这一点,读本节时就会自然放慢——前几节错了可以改配置重来,本节错了往往是换盘重来。

LUKS 的"一次性"还体现在备份策略的优先级上:别的配置错了可以从仓库重放,LUKS 头丢了则整卷数据连同备份一起蒸发——所以头文件备份的存放位置应当按"和数据本体分离、但和密码管理器同级"来定,而不是随手放进同盘的 home 目录。5.2 节把这条不可逆风险和 crypttab 开机解锁放在一起讲,就是为了在敲下大写 YES 之前,让风险与逃生路径同时出现在视野里。

5.1 概念:它保护什么、不保护什么 ​

LUKS(Linux Unified Key Setup)是 Linux 下的标准块设备加密方案,由 cryptsetup 管理。加密的是整个分区/卷的静态数据:硬盘被拔走、笔记本丢失、旧盘送人时,没有密钥就读不出内容。它不保护开机后的运行时数据——系统解锁之后,解密卷上的文件对内核与 root 就是明文;也不保护被 root 级攻击者控制的在线系统(可直接读已解锁卷或抓内存密钥)。

把 LUKS 与前面几节的边界划清楚很重要:TLS/SSH 加密的是链路上的数据(传输中),GPG 加密的是特定文件(可选择地静态),LUKS 加密的是整块设备的静态状态(at rest)。三者常被笼统称为"加密",但防的窃取场景完全不同——拦下网络包的攻击者会被 TLS 挡住,捡走硬盘的攻击者只会撞上 LUKS,而拿到 root 权限的攻击者对已解锁的三者都无感。威胁模型对不上,加密等于没加密,这是本篇反复回到的主题。

威胁模型说清楚了,适用场景也就清楚了:移动设备/笔记本必开,含敏感数据的服务器建议开,纯内网无敏感数据的服务器收益有限(还要权衡无人值守重启的解锁问题)。这条判断标准可以直接写进上线检查单:先问"这台机器的磁盘被物理拿到的概率有多大",再问"拿到后泄露的数据敏感度"——两个答案都高才值得承担解锁与恢复的运维成本。云主机常见"宿主机层面加密 + 自己管好数据"的分工,把物理层交给云厂商的合规承诺,自己专注应用层加密(见第 3、4 节),比在无法接触的硬件上强推 LUKS 更务实。

5.2 关键流程与不可逆风险 ​

概念边界讲清楚后,操作层面只剩一条主线:格式化 → 映射 → 文件系统 → 开机解锁,外加两处必须停下来确认的动作(核对设备名、备份头文件)。安装阶段在分区上创建 LUKS 容器(会摧毁该分区原有数据),然后建映射、格式化文件系统、写入 crypttab 实现开机解锁:

bash
sudo cryptsetup luksFormat /dev/sdb2    # 大写 YES 确认;数据将被覆盖
sudo cryptsetup open /dev/sdb2 crypt_data
sudo mkfs.ext4 /dev/mapper/crypt_data
# /etc/crypttab: crypt_data /dev/sdb2 none luks,discard

luksFormat 的确认提示写的是 Type uppercase yes——故意做得别扭,防止手滑。创建前必须确认设备路径:对错盘执行 luksFormat 不可恢复(除非有 LUKS header 备份)。强烈建议导出头文件备份:

bash
sudo cryptsetup luksHeaderBackup /dev/sdb2 --header-backup-file luks-header.bak

头文件备份之后还要验证它真的能用:拿备份文件在另一台机器(或同一台的隔离环境)走一次 cryptsetup luksOpen --header 的恢复路径,确认能提示 passphrase 而不是报"无效头"。没验证过的备份和没有备份只差一次坏运气的距离——这一条与第 7 节的"恢复演练"是同一条纪律在 LUKS 上的具体化。备份文件本身按密钥材料对待:离线存放、权限收紧、和 passphrase 不放在同一个抽屉。

头文件丢失 = 数据永久无法解密,无论 passphrase 是否正确。多 keyslot 是 LUKS 的恢复冗余机制:给自己、给恢复流程、给运维交接各留一槽,任一 passphrase 丢失都不至于全盘报废;轮换口令时用 luksAddKey/luksKillSlot 增删槽位,不要重建容器。恢复口令应离线保管(见第 6 节常见坑),保管方式与保管内容同等重要——写在贴着显示器的便签上,keyslot 设计得再好也只是仪式感。

LUKS2 是当前默认格式(cryptsetup 新版本默认 --type luks2),支持更灵活的密钥槽与 Argon2 KDF。服务器无人值守重启场景需要权衡:把 passphrase 写进 initramfs 等于变相解密(initramfs 泄露即等于密钥泄露),常见替代是网络解锁、TPM 自动解锁或不加密但严控物理与备份访问——没有"既全自动又防物理窃取"的免费午餐,按威胁模型取舍。TPM 方案的边界也要说清:它防的是"硬盘被拆走",防不住"整机在线被 root 控制"——攻击者能从 TPM 会话里触发解密,这与 LUKS 本身的离线防护定位并不矛盾,只是把信任根从 passphrase 挪到了硬件芯片。

6. 常见坑 ​

工具命令可以查手册,坑只有踩过(或读过别人踩)才有免疫力。下面十条按"造成不可逆损失"到"造成虚假安全感"排列,前四条一旦踩中基本无法事后补救,动手前值得重读——排序依据不是发生频率,而是事后能否补救:能重配的排后面,丢了就永远回不来的排前面。每条坑后面补一句"对应的正确动作",是为了让这节可以直接当变更前的 checklist 用,而不只是事故故事集。把十条再压成两句口诀也行:不可逆操作先备份、先验证(格式化、关口令、删私钥),看起来成功的命令先回读生效值(证书、sshd -T、签名者列表)——多数坑都能塞进这两句。

  1. 把哈希当加密。md5sum/sha256sum 不能还原原文,不提供机密性。需要可逆加密用 AES(openssl enc)或 GPG,需要密码存储用 Argon2/bcrypt。
  2. 私钥当普通文件备份。GPG 私钥、SSH 私钥、server.key 一旦进 git 或云盘裸存,等价于身份泄露。权限 600、独立加密备份、必要时 gpg --delete-secret-keys 清理临时导出。
  3. 先关 PasswordAuthentication 再配密钥,把自己锁在门外。永远先用新方式登录成功,再关旧方式;同时保留控制台/VNC 逃生通道。
  4. SSH 密钥用 RSA 2048 且无 passphrase。优先 ed25519;老设备才回退 RSA 3072+;私钥建议加 passphrase + ssh-agent。
  5. 验签只看命令退出码,不看签名者身份。gpg --verify 输出的 key ID 必须是你预期的那个,否则可能验了别人的"合法签名"。
  6. 证书只看"续期成功"不看 reload。ACME 续期钩子要真正执行 nginx -s reload/systemctl reload apache2,并监控 notAfter 剩余天数。
  7. 对 luksFormat 的设备名看都不看直接回车。不可逆操作前 lsblk 核对三遍;先做 luksHeaderBackup,再考虑 passphrase 轮换与多 keyslot(一个给自己、一个给恢复流程)。
  8. 认为全盘加密能防住在线攻击。LUKS 防的是离线窃取;防在线攻击靠最小权限、补丁与检测(见加固/入侵检测篇),两者威胁模型不同,不能互相替代。
  9. 三系包名混用。gnupg(Debian/Arch)与 gnupg2(RHEL)、cryptsetup 包名基本一致但仓库位置不同;跨发行版写脚本先 command -v 探测。
  10. 加密后不验证解密链路就归档。备份/传输场景务必做一次测试解密(用真实密钥跑通往返),否则可能在灾备当天才发现密钥不对——加密的可恢复性必须靠演练证明。

十条里第 1、8 条属于威胁模型误判(用错原语、用错防御对象),第 2、3、7 条属于密钥/设备操作事故,第 4、5、6、9 条属于配置与流程细节,第 10 条则是唯一一条专门防"未来的自己"的——加密体系的失败往往不在加密瞬间,而在恢复那一刻才暴露。自查时优先问第 10 条:这条数据,今天丢了密钥我救得回来吗?答不上来的,其它九条做得再好也是脆的。

7. 实战:把加密接进日常工作流 ​

前面六节分别对应一种原语或一个场景;落到实操,真正的问题是"明天上班先做哪件"。下面这份清单按优先级排序,每条都给出触发条件与完成标志,可以直接贴进团队的上线检查单——顺序本身也编码了风险判断:先堵正在流血的口子(入口认证),再补会流血的口子(供应链与传输),最后才是慢变量(设备与证书生命周期)。把清单当"第一天改什么"的地图,而不是一次性打勾的 TODO:六条里只有前三条是一次性收敛的,后三条会随人员、硬件与证书周期反复出现。清单还隐含一条依赖顺序:第 1 条的密钥是第 6 条演练的对象,第 5 条的 notAfter 告警要用到第 3 条的监控通道——先做前两条时就该把告警出口留好,否则第 5 条上线时又要重开一次变更。六条也可以按"谁受益"再分组:第 1、4 条主要保护你自己(不被锁、不被拖库),第 2、3、5 条保护的是下游消费者与未来排障的自己——安全清单写不清受益人时,优先级讨论就会退化成谁的嗓门大。

清单能落地的前提是每项都有完成标志(Definition of Done):第 1 条的完成标志不是"生成了密钥",而是"禁用口令后仍能从新会话登录且 sshd -T 确认 passwordauthentication no";第 2 条不是"跑过一次 sign",而是"消费方在另一台干净机器上验签通过"。没有可回读的完成标志,清单会在第一次人员变动后退化成勾选仪式——这与安全加固篇把九步都配上验收命令是同一条工程习惯。

清单的"触发条件"一列值得单独强调:安全习惯只有挂到具体事件上才容易坚持——新人入职(触发第 1 条)、发布流水线上线(触发第 2 条)、采购新盘(触发第 4 条)、证书到期前 30 天(触发第 5 条)。把六条分别绑定到已有的流程钩子,比另起一个"安全专项周"更可持续;反过来,没有触发条件的清单注定在下一个业务高峰被跳过。

最小可行的加密习惯清单,按优先级排序:

  1. 管理入口:SSH 全面切 ed25519 密钥,关口令(确认密钥可用之后)。
  2. 软件与配置分发:对外发布的脚本/配置做 gpg --detach-sign,消费方 gpg --verify 后再执行。
  3. 传输校验:大文件走 sha256sum 校验;跨不可信网络优先 TLS 通道而非裸 FTP/HTTP。
  4. 静态数据:含客户数据的笔记本/移动盘启用 LUKS;服务器评估威胁模型后决定是否全盘加密,并备份 LUKS 头。
  5. 证书运维:自动化续期 + 到期告警(监控 notAfter),续期钩子带 reload。
  6. 演练:每季度抽一次"恢复路径"——用备份私钥解密一个测试文件、用恢复 passphrase 解锁一个测试 LUKS 卷。没有演练过的加密,等于没有。

这六条覆盖了"传输、身份、静态、恢复"四个面,也正好对应本篇开篇的四件事。工具命令可以随发行版变(pacman -S/apt install/dnf install),但威胁模型与恢复纪律在三系上完全一致。

为什么把"演练"单列一条而不并进备份流程?因为加密系统的失败模式很特殊:密钥材料可能完好地躺在备份里,但没人记得 passphrase、没人知道私钥对应哪台机器、没人测试过恢复脚本能不能在干净环境跑通——故障不会在加密时报错,只会在解密时才现形,而那一刻往往就是灾备当天。把恢复演练固定成日历事件,等于把"未来某天的恐慌"换成"今天下午的三十分钟"。

第 1 条优先做,是因为它改变的是当前正在被攻击的面:公网上每台开着 22 端口的机器,口令认证都在接受持续扫描;切到密钥登录后,同一轮扫描的失败率会立刻归零,Fail2Ban 的告警噪音也随之下降——这是少数"改完当晚就有效果"的安全加固。第 2、3 条改变的是供应链与传输的可信度,收益在下一次软件分发或大文件传输时兑现。第 4、5 条绑定硬件采购与证书生命周期,节奏可以慢,但头文件备份与 notAfter 监控这两件事不能等——前者是不可逆操作前的保险绳,后者是"到期前 30 天还没人管"的最后告警。

第 6 条演练则从第一天就纳入日历,因为恢复能力不会随时间自己长出来,只会随着人员变动和格式遗忘而衰减。

把这六条塞进真实团队还有两个容易踩空的细节。其一,完成标志必须可验证:清单每项不能写"SSH 已加固"这种无法对账的描述,而应写成"ssh -o PreferredAuthentications=publickey 在禁用口令后仍能登录、且 sshd -T 显示 passwordauthentication no"——可回读的完成定义,才不会在人员轮换后退化成口头传统。其二,清单要区分"一次性切换"与"持续运行":第 1、2 条做完即收敛,之后只随人员变动复核;第 5、6 条则是无限循环的运维节奏,停一次就等于交还了对应的防护。很多团队把两者混在一张 checklist 里年复一年地"打勾",结果持续项在第二年就再也没人真正执行——分开记录、给持续项指定日历责任人才是可持续的做法。

参考资料 ​

读到这里,四条主线各自的"下一步深挖方向"其实已经分化:协议细节(TLS 密码套件、SSH KEX)适合继续啃实现方文档;信任与签名模型(GPG、仓库密钥)更适合结合本团队发布流程做制度设计;磁盘加密则是安装/运维向,以发行版手册与 cryptsetup 文档为准。按问题类型选文档,比按工具名收藏一堆 man page 更有效——多数"加密问题"问到最后是威胁模型问题,不是参数问题。本篇四条主线各有权威出处:协议与实现细节看 OpenSSL/OpenSSH 官方文档,信任与签名模型看 GnuPG 手册与 Arch Wiki 条目,磁盘加密以 cryptsetup 与发行版硬件加密指南为准。建议的阅读顺序与正文一致——先把 1 节的原语分工读透,再按实际需要深入对应工具的文档;反过来从某一工具的 man page 起步,容易记住一堆参数却说不清它保护的到底是什么威胁。查文档时还有一个省时间的习惯:先问"这是属性问题还是参数问题"——参数问题查 man 三行结束,属性问题要回到第 1 节的表,不然越查越偏。

相关页面 ​

基于 Apache License 2.0 许可发布