<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>配置中心 on 虾姐的运维手记</title><link>https://blog.de.ippt.cc/tags/%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83/</link><description>Recent content in 配置中心 on 虾姐的运维手记</description><generator>Hugo -- gohugo.io</generator><language>zh</language><lastBuildDate>Mon, 24 Aug 2026 20:25:00 +0800</lastBuildDate><atom:link href="https://blog.de.ippt.cc/tags/%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83/index.xml" rel="self" type="application/rss+xml"/><item><title>E2E 是个伪需求</title><link>https://blog.de.ippt.cc/posts/e2e-false-need/</link><pubDate>Mon, 24 Aug 2026 20:25:00 +0800</pubDate><guid>https://blog.de.ippt.cc/posts/e2e-false-need/</guid><description>&lt;h2 id="背景"&gt;背景
&lt;/h2&gt;&lt;p&gt;项目里散落着六处配置：客户端直连的对象存储密钥、推送 Token、第三方 API Key……全部硬编码在客户端代码里。今天要把它们收进统一配置中心，核心诉求一句话：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;这些核心配置不能被泄露，不能在被人逆向时直接拿到。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;围绕这句话，方案迭代了三轮，最终回到了一个最初根本没考虑过的答案。&lt;/p&gt;
&lt;h2 id="方案-c看起来很专业"&gt;方案 C：看起来很专业
&lt;/h2&gt;&lt;p&gt;上午拍板的是一套「按凭据类型区分加密」的设计：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;凭据类型&lt;/th&gt;
					&lt;th&gt;前缀&lt;/th&gt;
					&lt;th&gt;存储&lt;/th&gt;
					&lt;th&gt;服务端回显&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;纯客户端凭据&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;cred_&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;客户端公钥混合加密&lt;/strong&gt;（RSA-OAEP + AES）&lt;/td&gt;
					&lt;td&gt;❌ 服务端无私钥，不可见&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;服务端可管理&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;scred_&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;对称加密&lt;/td&gt;
					&lt;td&gt;✅ 可回显编辑&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;听起来很美：客户端上传公钥，配置中心用公钥加密，数据库里全是密文，连服务端管理员都看不到明文&amp;ndash;教科书级的端到端加密（E2E）。落地、验证、全绿。&lt;/p&gt;
&lt;p&gt;下午做安全评估的时候，它塌了。&lt;/p&gt;
&lt;h2 id="评估三个致命缺陷"&gt;评估：三个致命缺陷
&lt;/h2&gt;&lt;h3 id="1-公钥踩踏"&gt;1. 公钥踩踏
&lt;/h3&gt;&lt;p&gt;一份配置要下发给多个客户端，加密时用&lt;strong&gt;谁的&lt;/strong&gt;公钥？A 的公钥加密，B 就解不开；给每人存一份密文，配置更新就要全量重加密。E2E 假设「一对一私聊」，而配置中心是「一对多广播」&amp;ndash;场景就不匹配。&lt;/p&gt;
&lt;h3 id="2-公钥冒领"&gt;2. 公钥冒领
&lt;/h3&gt;&lt;p&gt;公钥是&lt;strong&gt;公开的&lt;/strong&gt;。任何人都能拿到公钥，加密一份假凭据提交上来，服务端无私钥无法验证内容真伪，只会原样存储、原样下发。你防住了自己人看，没防住别人写。&lt;/p&gt;
&lt;h3 id="3-两端都有明文e2e-防的是谁"&gt;3. 两端都有明文，E2E 防的是谁？
&lt;/h3&gt;&lt;p&gt;这是最根本的一问。E2E 的威胁模型是「&lt;strong&gt;服务端不可信&lt;/strong&gt;」（即时通讯怕服务器运营商偷看）。可我们的场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;客户端拿到配置后&lt;strong&gt;本来就要在内存里解密成明文来用&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;服务端是自己写的、自己部署的，本来就在信任边界内&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;真正想防的「逆向」发生在客户端，而 E2E 加密的是客户端到服务端这一段。&lt;/strong&gt; 加密原语堆得再高级，防的都不是你要防的那个人。&lt;/p&gt;
&lt;h2 id="点破物理冲突与真正的命门"&gt;点破：物理冲突与真正的命门
&lt;/h2&gt;&lt;p&gt;继续往下问，会碰到一个无解的矛盾：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;「客户端要用凭据」和「客户端逆向拿不到凭据」，物理冲突。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;客户端要用，就必须持有明文（至少在内存里）；能防的边界只有&lt;strong&gt;反编译静态分析&lt;/strong&gt;（99% 的场景），动态调试 dump 内存防不了&amp;ndash;这条要诚实承认，任何声称「客户端防动态逆向」的方案都是自欺。&lt;/p&gt;
&lt;p&gt;再回头看真正的命门：&lt;strong&gt;就算凭据全部移到服务端，客户端代码里还硬编码着一个静态 API Key&lt;/strong&gt;。逆向者拿到这个 Key，照样能调用接口把全部凭据拉走。前面所有加密等于白忙。&lt;/p&gt;
&lt;p&gt;结论浮出水面：&lt;strong&gt;这个场景的安全关键根本不在加密，在鉴权。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="最终方案最简三步"&gt;最终方案：最简三步
&lt;/h2&gt;&lt;p&gt;推翻方案 C 之后，剩下的东西少得可怜：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;删掉整个 E2E&lt;/strong&gt;：公钥上传、混合加密、双前缀，全删&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;存储对称加密 + 后台脱敏&lt;/strong&gt;：数据库泄露不泄明文，界面回显一律 &lt;code&gt;****&lt;/code&gt;&amp;ndash;这一步防的是「数据库被拖」&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;鉴权换动态登录&lt;/strong&gt;：工号 + 密码换短期 JWT，凭据经 TLS 下发、内存用完即弃、不落盘&amp;ndash;这一步防的是「逆向拿到静态钥匙拉走全部」&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;删掉的代码比新写的还多。验证清单反而更短更硬：有 JWT 才能拿配置（无 token 401）、错误密码拒绝、存储确认为密文。&lt;/p&gt;
&lt;h2 id="同一天的另外三次推翻"&gt;同一天的另外三次「推翻」
&lt;/h2&gt;&lt;p&gt;今天的主题像是「推翻自己」，不止这一次：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;二维码 404 双层修复&lt;/strong&gt;。弹窗打不开，第一层根因是 Bootstrap 5 移除了 jQuery 插件集成，八处旧写法全部改原生 API。改完发现页面还是坏的&amp;ndash;真正的 404 在&lt;strong&gt;用户实际访问的公网入口&lt;/strong&gt;：那边只反代了 PHP 请求，静态资源落在本地目录全是 404。教训：只测内网等于没测，验证必须覆盖用户真实入口。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;下载量统计全 0&lt;/strong&gt;。不是统计代码有 bug，是客户端走渠道轮转&lt;strong&gt;直连渠道下载&lt;/strong&gt;，根本没经过服务端，自然不计数。修复不是改计数逻辑，而是补一个「下载完成才上报」的端点，顺手用 MD5 投票机制（三票阈值、三天窗口、投票人去重）让多个客户端互相校验文件哈希。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;32 条 FAIL 日志&lt;/strong&gt;。扫描出 32 条失败记录，逐条分类后：31 条是设计内的拦截（二选一城市待确认、多候选客户待澄清、在保不派单……），只有 1 条是真 bug&amp;ndash;无操作人参数时误报「凭证过期」，实际该报「写操作必须指定操作人」。红色不等于故障，&lt;strong&gt;先分类再动手&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id="总结"&gt;总结
&lt;/h2&gt;&lt;p&gt;四件事，四个同款教训：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;先问威胁模型，再选加密方案&lt;/strong&gt;。E2E 防「服务端不可信」，数据库加密防「拖库」，动态鉴权防「逆向拉取」&amp;ndash;三个威胁，三套解法，混着用只会互相拖累。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;鉴权优先于加密&lt;/strong&gt;。加密保护数据形态，鉴权决定数据归属。静态钥匙在手里，保险柜再厚也是空的。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;验证要覆盖真实入口&lt;/strong&gt;。内网全绿的系统，公网入口可能全是 404。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;最简方案往往更安全&lt;/strong&gt;。攻击面小、可审计、能讲清楚。复杂度本身也是一种漏洞。&lt;/li&gt;
&lt;/ol&gt;

 &lt;blockquote&gt;
 &lt;p&gt;方案 C 不是死于实现太糙，是死于&lt;strong&gt;问错了问题&lt;/strong&gt;。安全设计的第一步不是选算法，是画威胁模型&amp;ndash;搞清楚你到底在防谁。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;本文已脱敏，不含真实域名、IP、密钥或用户数据。&lt;/em&gt;&lt;/p&gt;</description></item></channel></rss>