<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>董锐</title><description>网络 · 身份 · 企业信息化</description><link>https://dr.free--china.com/</link><templateTheme>Firefly</templateTheme><templateThemeVersion>6.16.6</templateThemeVersion><templateThemeUrl>https://github.com/CuteLeaf/Firefly</templateThemeUrl><lastBuildDate>2026年9月3日 18:15:03</lastBuildDate><item><title>企业 AD 从 0 到 1：域控、终端、证书、无线和 SSO</title><link>https://dr.free--china.com/posts/ad-zero-to-one/</link><guid isPermaLink="true">https://dr.free--china.com/posts/ad-zero-to-one/</guid><description>在一家从没有域的制造企业里，把 Active Directory、DNS、证书、SCCM、RADIUS 和 Entra ID 一次铺起来。这篇写边界怎么划、坑在哪，不写客户内网细节。</description><pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这家公司原来没有域。账号在各处散着：电脑是本地用户，Wi-Fi 是预共享密钥，微软 365 是另一套，业务系统再各自开户。人一多，入职离职、权限回收、无线准入全靠手工。&lt;/p&gt;
&lt;p&gt;我的任务是把身份底座从 0 铺到能日常运转：AD 管人、SCCM 管电脑、RADIUS 管无线、Entra ID 管微软云、LDAP 把其它系统接进同一套登录。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;先定边界&lt;a href=&quot;#先定边界&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;从 0 建域最容易做成「一台 Windows Server 装完 AD 就算完」。那只是目录服务起来了，身份问题一个没解决。&lt;/p&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;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;目录&lt;/td&gt;&lt;td&gt;人、组、OU、GPO&lt;/td&gt;&lt;td&gt;AD DS&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;解析&lt;/td&gt;&lt;td&gt;内网名字、公司 DNS 出口&lt;/td&gt;&lt;td&gt;AD 上的 DNS&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;终端&lt;/td&gt;&lt;td&gt;加域电脑的清单、远程、补丁、报表&lt;/td&gt;&lt;td&gt;Configuration Manager&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;认证出口&lt;/td&gt;&lt;td&gt;Wi-Fi、门户、业务系统、微软云&lt;/td&gt;&lt;td&gt;NPS / AD CS / Entra ID / LDAP&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;虚拟化平台上先部署操作系统、SQL Server 和报表库，再装角色。SQL 是 SCCM 和报表的前提，不要倒过来装。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;DNS 不只是域的附属&lt;a href=&quot;#dns-不只是域的附属&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;AD 起来之后，DNS 承担了整个公司的解析出口。这件事比「给域控制器加个角色」麻烦：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;内网记录必须权威，不能被公网 DNS 抢走&lt;/li&gt;
&lt;li&gt;出网解析要稳定，还得处理个别&lt;strong&gt;政府网站、厂家站点&lt;/strong&gt;在公共 DNS 上表现异常的情况——有的要指定转发，有的要拆开条件转发器，有的只能写静态记录&lt;/li&gt;
&lt;li&gt;客户端只认这一跳，DNS 一抖，加域、GPO、证书申请会一起抖&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;所以 DNS 是身份底座的一部分，不是网络组顺手代管的服务。&lt;/p&gt;&lt;p&gt;IIS 用来挂门户和部分内部发布，跟证书服务放在同一套身份语境里，避免门户是一套账号、域是另一套。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;SCCM：把「加了域」变成「管得住」&lt;a href=&quot;#sccm把加了域变成管得住&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;电脑加域只说明它认这套账号。真正要的是：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;边界清楚：哪些网段、哪些站点属于哪套管理点&lt;/li&gt;
&lt;li&gt;清单可视化：谁的机器、什么系统、在不在线&lt;/li&gt;
&lt;li&gt;远程：协助而不是让人把电脑抱过来&lt;/li&gt;
&lt;li&gt;报表：领导问「域里有多少台、多少没打补丁」时有数&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Configuration Manager 从边界、发现、客户端推送一路建下来。这一步的工作量不在点安装向导，而在&lt;strong&gt;边界不要画错&lt;/strong&gt;——画错了，客户端会去找一个它到不了的管理点，表现为「加了域但 SCCM 里看不见」。&lt;/p&gt;&lt;p&gt;密码自助（AD Self-Service）是给帮助台减负的：解锁和重置不必每次工单打到 IT。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;证书、RADIUS 和无线 SSO&lt;a href=&quot;#证书radius-和无线-sso&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;无线如果继续用 PSK，域建得再完整也只覆盖到有线电脑。制造企业里手机、笔记本、访客终端都走 Wi-Fi，PSK 等于把内网口子开在空气里。&lt;/p&gt;&lt;p&gt;做法是：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;AD CS&lt;/strong&gt; 签发 NPS 和无线证书，避免自签证书在客户端弹一堆警告&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;NPS RADIUS&lt;/strong&gt; 接华为 AC，802.1X / Portal 认证落到域账号&lt;/li&gt;
&lt;li&gt;账号源对齐 &lt;strong&gt;Entra ID&lt;/strong&gt;（Azure AD）：人走一套组织架构，Wi-Fi、Teams、Outlook 认同一套身份&lt;/li&gt;
&lt;li&gt;只允许企业组织账号接入，访客走隔离 VLAN&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;做到这一步，Wi-Fi 登录和办公套件 SSO 是同一件事的两个出口，而不是两套账号。&lt;/p&gt;&lt;p&gt;AD 与 Azure AD / Entra ID 的同步，用来在本地管理员工的微软账号和策略。其它还没云化的系统，走 &lt;strong&gt;LDAP&lt;/strong&gt; 接进同一目录，把 SSO 补齐——不要每个系统再造一遍用户表。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;不做什么&lt;a href=&quot;#不做什么&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;不在第一期上复杂的条件访问和全员 MFA 强制（先保证加域、无线、解锁能日常运转）&lt;/li&gt;
&lt;li&gt;不把业务系统的权限模型塞进 AD 组里一次性「完美映射」（组可以先粗，权限细了再收）&lt;/li&gt;
&lt;li&gt;不在文章里写网段、主机名和客户内网拓扑&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;结果&lt;a href=&quot;#结果&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;有了这套底座之后，入职是加组，离职是禁用账号，无线和办公套件跟着失效；电脑在 Configuration Manager 里看得见、连得上、报得出。后面的防火墙策略、Zabbix 纳管、保密产线准入，都站在这套身份上面，而不是再各搞一套。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>人人麻将：从规则状态机到 Android 包的四川血战麻将</title><link>https://dr.free--china.com/posts/majiang-blood-battle/</link><guid isPermaLink="true">https://dr.free--china.com/posts/majiang-blood-battle/</guid><description>一个四人实时对战的川麻项目。服务端用 Node.js + Socket.IO 把规则做成纯状态机，客户端用 Cocos Creator 出 H5 和 Android 包，现在跑在自己的 VPS 上。</description><pubDate>Thu, 20 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这是我做得最完整的一个项目：&lt;strong&gt;四川血战到底&lt;/strong&gt;，四人实时对战，有真人房也有 AI 补位，H5 和 Android 包都出了，现在跑在自己的 VPS 上。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;为什么是麻将&lt;a href=&quot;#为什么是麻将&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;麻将看着简单，实际是个很好的服务端练手题：它同时具备&lt;strong&gt;强规则&lt;/strong&gt;、&lt;strong&gt;多人实时&lt;/strong&gt;、&lt;strong&gt;状态必须绝对一致&lt;/strong&gt;三个特征。任何一处判断写歪，四个客户端立刻就会吵起来。写完一遍麻将，基本把状态同步该踩的坑踩了一轮。&lt;/p&gt;&lt;p&gt;而且川麻的「血战到底」比标准麻将更麻烦——有人胡牌后不是结束，而是&lt;strong&gt;离桌，剩下的人继续打&lt;/strong&gt;。这意味着对局状态机不能简单地按「一局 = 四个人从头打到尾」建模。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;架构&lt;a href=&quot;#架构&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&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;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;majiang-server&lt;/code&gt;&lt;/td&gt;&lt;td&gt;规则引擎 + 房间服务&lt;/td&gt;&lt;td&gt;Node.js、Socket.IO&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;majiang-app&lt;/code&gt;&lt;/td&gt;&lt;td&gt;客户端&lt;/td&gt;&lt;td&gt;Cocos Creator 3.8.8、TypeScript&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;majiang-godot-commercial-fork&lt;/code&gt;&lt;/td&gt;&lt;td&gt;另一条客户端技术路线的试验&lt;/td&gt;&lt;td&gt;Godot&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;关键的一条设计决定：&lt;strong&gt;规则引擎和网络层彻底分开&lt;/strong&gt;。&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;majiang-server/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;src/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;core/      # 纯函数式的规则与对局状态机，不认识 socket&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;server/    # HTTP + Socket.IO，只负责收发和广播&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;test/        # 直接对 core 做单元测试，不起服务&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;core&lt;/code&gt; 里没有任何网络代码，它就是一个 &lt;code&gt;(状态, 动作) =&amp;gt; 新状态&lt;/code&gt; 的状态机。好处非常直接：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;测规则不用起服务器，&lt;code&gt;npm run test:core&lt;/code&gt; 几秒跑完&lt;/li&gt;
&lt;li&gt;AI 就是一个「读状态、返回动作」的函数，和真人玩家走完全同一条代码路径&lt;/li&gt;
&lt;li&gt;以后要换传输层（比如换成 WebSocket 原生或 KCP），&lt;code&gt;core&lt;/code&gt; 一行不用动&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;规则实现的几个点&lt;a href=&quot;#规则实现的几个点&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;牌墙&lt;/strong&gt;：108 张，只有万、筒、条，没有风牌和箭牌。这是川麻和国标最直观的区别。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;定缺&lt;/strong&gt;：开局每人必须选一门花色作为「缺门」，之后不能碰杠胡这门牌，手里的缺门牌必须优先打出去。这一步是川麻的灵魂，也是 AI 最容易写蠢的地方。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;没有吃&lt;/strong&gt;：川麻只有碰、杠、胡，没有吃。少了一个动作，但优先级判定并没有变简单——同一张牌可能同时有人要碰、有人要胡，得按「胡 &amp;gt; 杠 &amp;gt; 碰」的优先级仲裁，还要处理一炮多响。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;血战到底&lt;/strong&gt;：某人胡牌后从牌桌移除，但&lt;strong&gt;牌局继续&lt;/strong&gt;，直到只剩一人或牌墙摸完。所以对局状态里必须显式维护「还在场的玩家」这个集合，而不是假定永远是四个人。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;一次缺陷审计&lt;a href=&quot;#一次缺陷审计&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;项目跑了一段时间后我做过一轮系统性的缺陷排查，一共整理出 20 条问题，修掉了 17 条。剩下 3 条是需要改数据结构的，放到了后面的迭代里。&lt;/p&gt;&lt;p&gt;这轮审计最大的收获不是修了多少 bug，而是确认了一件事：&lt;strong&gt;凡是能在 &lt;code&gt;core&lt;/code&gt; 层用单元测试复现的问题，修起来都很快；凡是只能靠「开四个浏览器手动打一局」复现的，都很慢。&lt;/strong&gt; 后来我把能下沉的判断全部往 &lt;code&gt;core&lt;/code&gt; 挪了。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;客户端与打包&lt;a href=&quot;#客户端与打包&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;客户端用 Cocos Creator 3.8.8 + TypeScript。选它的主要原因是&lt;strong&gt;一套工程同时出 H5 和 Android&lt;/strong&gt;，而对局逻辑完全复用服务端已有的协议，客户端不重写任何规则——客户端只负责渲染和把玩家操作发上去，所有判定以服务端为准。&lt;/p&gt;&lt;p&gt;Android 出包这一步坑最多，主要是 Gradle 和 NDK 的版本匹配问题。这部分我单独记了笔记，之后补一篇。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;部署&lt;a href=&quot;#部署&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;服务端直接 tar over ssh 推到 VPS，不走 CI。原因很实际：这个项目的部署频率不高，而且&lt;strong&gt;有几个目录（玩家数据、房间快照）绝对不能被覆盖&lt;/strong&gt;，走脚本反而容易手滑。改数据相关的东西之前必须先停服。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;后面要做的&lt;a href=&quot;#后面要做的&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt; 血流成河玩法&lt;/li&gt;
&lt;li&gt; 账号和金币持久化（现在是内存，重启清零）&lt;/li&gt;
&lt;li&gt; 换三张&lt;/li&gt;
&lt;li&gt; 完整番型表&lt;/li&gt;
&lt;/ul&gt;&lt;hr /&gt;&lt;blockquote&gt;&lt;p&gt;这篇是项目概览。具体到某一块（比如状态机怎么设计、Android 出包踩了什么坑）我会单独开文章写。&lt;/p&gt;&lt;/blockquote&gt;&lt;/section&gt;</content:encoded></item><item><title>把 Agent 用在信息化交付里：方案、交底和预算</title><link>https://dr.free--china.com/posts/ai-agent-ops/</link><guid isPermaLink="true">https://dr.free--china.com/posts/ai-agent-ops/</guid><description>在镭射沃期间把 GLM、Gemini、Grok、Claude、GPT 用进日常：写建设方案、整理技术文档、做工程预算，以及跟集成商做功能梳理和技术交底。</description><pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;信息化项目里最耗时间的，经常不是敲命令，而是把一件事写清楚：要做什么、谁来做、做到什么程度、花多少钱、风险在哪。以前这些靠一个人熬文档；现在 Agent 可以显著缩短&lt;strong&gt;第一版&lt;/strong&gt;的时间，前提是你知道它哪句能信、哪句必须自己改。&lt;/p&gt;
&lt;p&gt;我日常会同时用 GLM、Gemini、Grok、Claude、GPT（含 Claude Code 这类能碰仓库和命令的 Agent）。不是因为追新，而是不同模型在「中文方案结构 / 英文资料检索 / 代码和配置草稿」上各有长处，交叉看一遍比迷信一家要稳。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;用在哪，不用在哪&lt;a href=&quot;#用在哪不用在哪&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;适合：&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;建设方案的目录、现状分析、分阶段目标&lt;/li&gt;
&lt;li&gt;把现场调研纪要收成功能清单&lt;/li&gt;
&lt;li&gt;工程预算的科目框架（设备、实施、维保、培训、预备费）&lt;/li&gt;
&lt;li&gt;给集成商的技术交底提纲：接口、责任面、验收口径&lt;/li&gt;
&lt;li&gt;把厂商文档翻译成「我们这次到底要开哪些功能」&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;不适合直接定稿：&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;最终报价和品牌选型（价格和货期必须问过渠道）&lt;/li&gt;
&lt;li&gt;安全策略的放行清单（模型看不见你的现网）&lt;/li&gt;
&lt;li&gt;合同条款和法律承诺&lt;/li&gt;
&lt;li&gt;任何带客户保密细节的原文外发&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;一句话：Agent 产出的是&lt;strong&gt;可改的草稿和检查清单&lt;/strong&gt;，不是可盖章的文件。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;技术交底怎么用&lt;a href=&quot;#技术交底怎么用&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;找第三方集成商时，最怕两边各理解一套。我会先让 Agent 根据调研记录生成一份功能对照表：模块、输入输出、依赖、验收方式、不在范围内的事项。然后自己按现场改，再拿着这张表开会。&lt;/p&gt;&lt;p&gt;好处是会议上吵的是表里的行，而不是「我觉得你应该懂」。交底结束，这张表就能进项目文档，预算也能按行估，而不是拍一个整数。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;和本职的关系&lt;a href=&quot;#和本职的关系&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;网络、身份、防火墙、Zabbix 仍然要自己设计和验收。Agent 把文档和沟通的密度拉开之后，我才能把时间留在现网和产线隔离这种不能写错的地方。智能化建设不是再做一个聊天机器人给领导看，而是让方案、预算、交底这些交付物的质量稳定在可评审的水平。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>跨境 SD-WAN 和多品牌防火墙：一个总部，四地出口</title><link>https://dr.free--china.com/posts/cross-border-sdwan/</link><guid isPermaLink="true">https://dr.free--china.com/posts/cross-border-sdwan/</guid><description>深圳总部辐射越南、香港、韩国、苏州。专线混互联网、策略路由、Fortinet 与 AhnLab 的整合，以及用 Zabbix 把设备纳管和报表先跑起来。</description><pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;制造企业一旦在海外设厂，网络就不再是「机房里那几台交换机」。深圳要访问越南的业务系统，韩国要回总部的身份服务，香港有独立的监管和线路习惯，苏州又是另一套园区。每地一个防火墙品牌、一条专线、一套习惯，最后一定会出现：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;访问绕远、专线闲着互联网堵着&lt;/li&gt;
&lt;li&gt;策略在四套设备上各写一遍，改漏一个口子&lt;/li&gt;
&lt;li&gt;监控各看各的，故障要打电话问「你们那边灯是不是红的」&lt;/li&gt;
&lt;/ul&gt;
&lt;section&gt;&lt;h2&gt;骨干怎么铺&lt;a href=&quot;#骨干怎么铺&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;目标很明确：&lt;strong&gt;深圳总部是枢纽&lt;/strong&gt;，越南、香港、韩国、苏州是分支。&lt;/p&gt;&lt;p&gt;SD-WAN 在这里做三件事：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;混合接入&lt;/strong&gt;：专线保关键系统，互联网做备份和办公突增，不要赌单一运营商&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;链路优选&lt;/strong&gt;：延迟、丢包、抖动进来当选路依据，而不是静态「这条永远主、那条永远备」&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;策略路由&lt;/strong&gt;：身份、监控、办公、产线走不同路径和隧道，避免所有流量挤一条 Overlay&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;稳定性运维比开局更耗时间。跨境链路的故障经常不在你的设备上：对端运营商、当地防火墙策略、DNS 出口、证书过期，都会表现为「访问总部很慢」。所以骨干要和身份、DNS 一起看，不能只盯隧道状态。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;防火墙：整合，而不是换齐&lt;a href=&quot;#防火墙整合而不是换齐&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;现场已经存在 Fortinet、AhnLab 以及其它品牌。一上来「全部换成同一家」在预算、窗口和当地支持上都走不通。&lt;/p&gt;&lt;p&gt;我做的是&lt;strong&gt;策略层整合&lt;/strong&gt;：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;对象（地址 / 服务 / 时间）命名对齐，四地能对得上「这是同一类东西」&lt;/li&gt;
&lt;li&gt;安全策略按「源区域 → 目的 → 谁 → 干什么」写，禁止在设备里堆编号注释只有原作者能懂的规则&lt;/li&gt;
&lt;li&gt;变更走同一套评审：开端口先问身份和产线分区，再问防火墙&lt;/li&gt;
&lt;li&gt;后期迭代时，能合并的合并，能下沉到 SD-WAN 的不下沉到每台墙&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;香港、越南、韩国的合规和厂商支持半径不一样，AhnLab 在韩系环境里常见，Fortinet 在总部和部分海外出口常见。整合的目标是&lt;strong&gt;运维语言统一&lt;/strong&gt;，不是 Logo 统一。&lt;/p&gt;&lt;p&gt;核心设备升级和集团网络架构规划放在同一条线上：先把出口、核心、汇聚的角色写清楚，再决定哪台该退役。否则升级会变成「新设备按旧逻辑配一遍」。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Zabbix：先看见，再自动&lt;a href=&quot;#zabbix先看见再自动&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;没有统一监控时，四地故障靠聊天软件。Zabbix 服务端搭起来之后，优先做三件不花哨但每天用得上的事：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;设备纳管&lt;/strong&gt;：防火墙、交换机、关键服务器、隧道对端，先进模板再谈漂亮大屏&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;策略&lt;/strong&gt;：什么该告警、谁收、多久升级，避免凌晨被磁盘 IO 的 Warning 叫醒&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;自动化报表&lt;/strong&gt;：可用率、流量、故障次数对接出去，给周会一个数而不是截图&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Zabbix 不替代厂商自家的分析器，它解决的是「跨品牌、跨站点，有一个共同的眼睛」。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;和身份的关系&lt;a href=&quot;#和身份的关系&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;跨境网络如果不管身份，就会变成「专线很通，谁都能走」。AD / RADIUS / Entra ID 起来之后，分支访问总部系统可以按组授权，Wi-Fi 和办公套件跟同一套账号。网络提供路，身份提供「谁可以上路」。&lt;/p&gt;&lt;p&gt;具体拓扑、公网地址和隧道参数不在这里展开。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>保密产线的网络怎么隔离：分区、准入、访客和审计</title><link>https://dr.free--china.com/posts/secure-line-network/</link><guid isPermaLink="true">https://dr.free--china.com/posts/secure-line-network/</guid><description>面向苹果供应链客户的保密产线安保。只写可公开的方法：办公网与产线网怎么分开、终端怎么准入、访客怎么隔离、审计看什么。不写客户工艺、产品线和现场细节。</description><pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;消费电子供应链对「产线网」的要求，和普通办公网不是一回事。客户会把保密写进合同和现场审计清单：哪些人能进、哪些设备能插、数据能不能出去、访客手机怎么办。IT 的工作不是写一篇保密承诺，而是把这些要求落到&lt;strong&gt;网络分区、终端、门禁和日志&lt;/strong&gt;上。&lt;/p&gt;
&lt;p&gt;下面只写方法。客户名称在简历里用于说明项目背景，现场拓扑、产品线、产量和审计条款不在公开文章里出现。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;先把网分开&lt;a href=&quot;#先把网分开&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&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;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;产线网&lt;/td&gt;&lt;td&gt;工控、工位电脑、必要的采集&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;/td&gt;&lt;td&gt;走身份认证，按组访问&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&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;「隔离」不是 VLAN 号不同就结束。要看三件事：三层能不能互访、无线会不会漂到错误 SSID、运维跳板会不会同时踩两张网。跳板必须受控，不能变成产线网的后门。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;终端准入，而不是信任插口&lt;a href=&quot;#终端准入而不是信任插口&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;产线最常见的口子是「找个空闲网口插上」。应对是：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;只允许加入域、纳入 Configuration Manager 的电脑&lt;/strong&gt;进产线或办公有线&lt;/li&gt;
&lt;li&gt;未注册终端进隔离或直接拒绝&lt;/li&gt;
&lt;li&gt;存储介质、私接热点、个人电脑按客户要求禁用或登记&lt;/li&gt;
&lt;li&gt;无线走 802.1X / Portal，企业账号才关联有权限的 SSID&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;身份底座（AD、证书、RADIUS）在这里不是「IT 内部建设」，而是保密审计能看懂的控制点：人走账号，电脑走清单，网络认这两者。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;人的边界：门禁、监控、访客&lt;a href=&quot;#人的边界门禁监控访客&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;网络策略管的是包，管不了「人已经站在工位旁边」。需要安防系统补上：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;门禁权限最小化，产线区域与办公区域分权，外包和访客单独组&lt;/li&gt;
&lt;li&gt;视频监控覆盖出入口、产线通道和公共区域，权限、录像周期、异常告警要能拿出来给审计看&lt;/li&gt;
&lt;li&gt;访客网络单独 VLAN / SSID，默认只能上网，不能进产线网段，也不能扫到内部打印机和文件共享&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;办公区、公共区域的访问控制经常被当成「无线密码换一下」。在保密项目里，它和产线隔离是同一份答卷。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;审计看什么&lt;a href=&quot;#审计看什么&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;审计不太关心你用了哪家防火墙的哪条特性名字，关心的是：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;产线网和办公网之间有没有明确的允许列表&lt;/li&gt;
&lt;li&gt;离职和项目结束之后，账号、门禁、终端有没有关掉&lt;/li&gt;
&lt;li&gt;访客有没有单独的网络和停留记录&lt;/li&gt;
&lt;li&gt;变更有没有人审、日志留不留得住&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;所以日志要能对上人：防火墙会话、RADIUS 认证、AD 登录、门禁事件，至少要能在同一时间轴上对得起来。对不起来的隔离，审计会当成没做。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;和日常运维的关系&lt;a href=&quot;#和日常运维的关系&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这套东西一旦上线，就不能靠「熟悉现场的那个人记得」。策略变更走评审，Zabbix 看着关键链路和服务器，SCCM 看着终端是否还在清单里。保密不是一次施工，是之后每次开端口都要再问一遍：这条路是不是产线需要的。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>用 Astro + Firefly 搭这个站，以及 pnpm 装不上的真正原因</title><link>https://dr.free--china.com/posts/building-this-site/</link><guid isPermaLink="true">https://dr.free--china.com/posts/building-this-site/</guid><description>选主题的过程、为什么最后选了 Firefly，以及国内装依赖时 npmmirror 会在大包上给你一个 302，把 pnpm 卡死。</description><pubDate>Wed, 02 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;一直想有个地方把自己做过的项目集中放出来，而不是散在几个 GitHub 仓库里。这周把它搭起来了。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;选型&lt;a href=&quot;#选型&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&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;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Hugo (PaperMod / Stack)&lt;/td&gt;&lt;td&gt;最快最稳，但改 Go template 很难受&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Next.js (tailwind-nextjs-starter-blog)&lt;/td&gt;&lt;td&gt;博客能力最强，但对纯展示站来说重了&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Astro (Fuwari / Firefly)&lt;/td&gt;&lt;td&gt;默认零 JS，组件化改起来最顺手&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;最后选 &lt;strong&gt;&lt;a href=&quot;https://github.com/CuteLeaf/Firefly&quot; target=&quot;_blank&quot;&gt;Firefly&lt;/a&gt;&lt;/strong&gt;，它是 Fuwari 的二次开发版，功能补得很全，而且更新非常勤。&lt;/p&gt;&lt;p&gt;选它主要看中两点：一是&lt;strong&gt;配置驱动&lt;/strong&gt;——绝大部分东西在 &lt;code&gt;src/config/&lt;/code&gt; 下改 TypeScript 文件就行，不用碰组件；二是它自带一个「书签导航」页，那个页面的数据结构（分组 + 卡片 + 图标 + 描述）&lt;strong&gt;正好就是一个项目展示页需要的形状&lt;/strong&gt;，我直接把它改造成了项目页，一行组件代码都没改。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;装依赖卡了半小时&lt;a href=&quot;#装依赖卡了半小时&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这部分值得单独说，因为国内大概率都会遇到。&lt;/p&gt;&lt;p&gt;我的 npm 源是 &lt;code&gt;registry.npmmirror.com&lt;/code&gt;，平时很好用。但 &lt;code&gt;pnpm install&lt;/code&gt; 跑了二十多分钟，1135 个包里有 19 个死活装不上，报的都是同一个错：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[WARN] GET https://registry.npmmirror.com/typescript/-/typescript-6.0.3.tgz error (23)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[WARN] GET https://registry.npmmirror.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.3.tgz error (23)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[WARN] GET https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz error (23)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;✗ Lockfile failed supply-chain policy check&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[ERR_PNPM_BROKEN_METADATA_JSON] The operation was aborted due to timeout&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;注意失败的&lt;strong&gt;全是大包&lt;/strong&gt;：typescript、sharp、esbuild、wrangler、workerd、biome、pagefind、lightningcss。小包一个没出问题。&lt;/p&gt;&lt;p&gt;直接 curl 一下就看明白了：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;curl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-o&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/dev/null&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-w&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;%{http_code} %{speed_download}\n&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;https://registry.npmmirror.com/typescript/-/typescript-6.0.3.tgz&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 302, 55 B/s&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;curl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-o&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/dev/null&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-w&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;%{http_code} %{speed_download}\n&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 200, 786029 B/s&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;npmmirror 对超过一定体积的 tarball 会返回 302 跳到它自己的 CDN，而这个跳转在我这里跟不动。&lt;/strong&gt; pnpm 重试几轮之后连元数据缓存都写坏了，报出一个和真实原因完全无关的 &lt;code&gt;BROKEN_METADATA_JSON&lt;/code&gt;。&lt;/p&gt;&lt;p&gt;解决办法很简单，这一次装换直连官方源：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;pnpm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--registry=https://registry.npmjs.org&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;40 秒装完。之前二十多分钟已经把 1116 个小包缓存进 store 了，换源之后只需要补那 19 个。&lt;/p&gt;&lt;p&gt;顺带一提，克隆仓库本身也慢——Firefly 仓库带历史有 130MB。直接下 tarball 只有 19MB：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;curl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-L&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-o&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;firefly.tar.gz&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;https://github.com/CuteLeaf/Firefly/archive/refs/heads/master.tar.gz&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;改了什么&lt;a href=&quot;#改了什么&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;关掉了主题自带的追番、VNDB、AnimeList、相册、友链、留言、打赏页，只留博客 + 项目 + 关于&lt;/li&gt;
&lt;li&gt;把「书签导航」改造成项目页，导航栏提到顶级&lt;/li&gt;
&lt;li&gt;换掉横幅文案、logo、站点信息&lt;/li&gt;
&lt;li&gt;把主题默认引用的作者 CDN 背景视频去掉了——那是别人的带宽&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;还没做的&lt;a href=&quot;#还没做的&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt; 换成履历用的头像和机房横幅&lt;/li&gt;
&lt;li&gt; 把站点改成简历的项目附录，补上企业信息化案例&lt;/li&gt;
&lt;li&gt; 补每个项目的封面图&lt;/li&gt;
&lt;li&gt; 部署到 Cloudflare Pages&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;</content:encoded></item><item><title>订阅制服务的用量计量和三通道支付</title><link>https://dr.free--china.com/posts/subscription-billing-system/</link><guid isPermaLink="true">https://dr.free--china.com/posts/subscription-billing-system/</guid><description>一套跑在 GCP 上的订阅计费：支付宝 / PayPal / USDT 三条通道，重构了原实现里用量统计对不上账的部分。只写计量和通道边界，不写业务名和域名。</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;订阅服务看起来是「按月扣一次钱」，真正难的是&lt;strong&gt;用量&lt;/strong&gt;和&lt;strong&gt;通道&lt;/strong&gt;两件事叠在一起：用户用了多少要能说清楚，钱从三条完全不同的通道进来还要对得上同一笔订单。&lt;/p&gt;
&lt;p&gt;这套系统跑在 GCP 上，Laravel + Docker。业务形态不在这里展开，只写计费层怎么拆。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;用量为什么容易错&lt;a href=&quot;#用量为什么容易错&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;原实现把「发生了一次使用」和「账上该记一笔」写在同一条请求路径里。于是会出现：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;重试一次，用量加两次&lt;/li&gt;
&lt;li&gt;通道回调晚到，账期已经切到下个月&lt;/li&gt;
&lt;li&gt;统计用的是缓存里的近似值，对账用的是数据库，两套数永远差一截&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;我把它拆开：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;事件&lt;/strong&gt;：系统里真实发生的使用，只追加，不改历史&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;计量&lt;/strong&gt;：按账期把事件聚合成用量，可重算&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;账单&lt;/strong&gt;：计量结果生成应付，和支付通道无关&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;支付&lt;/strong&gt;：账单去找通道，通道只认识金额和单号&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;用量对不上时，重算计量即可，不必去改支付流水。支付对不上时，查通道，不必去改事件表。这是从 Jeepay 那条通道经验里带过来的同一条原则：&lt;strong&gt;账本和通道不要写在一个 if 里&lt;/strong&gt;。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;三条通道&lt;a href=&quot;#三条通道&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;支付宝、PayPal、USDT 的对账语言不一样：一个是商户订单号，一个是 Capture，一个是链上确认。对上层账单只暴露「待支付 / 已支付 / 失败 / 关闭」。&lt;/p&gt;&lt;p&gt;USDT 尤其不能只信一次通知。链上确认数、重复支付、少付，都要当成一等公民，而不是「先入账再人工改」。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;部署&lt;a href=&quot;#部署&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Docker Compose 分环境。计量任务和 Web 进程分开跑，避免请求高峰把账期聚合挤掉。密钥和回调地址按环境隔离，文章里不列。&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;业务名、域名、节点和商户号不在公开材料里出现。这篇只说明计费为什么要分层。&lt;/p&gt;&lt;/blockquote&gt;&lt;/section&gt;</content:encoded></item><item><title>给 Jeepay 加一条东南亚支付通道</title><link>https://dr.free--china.com/posts/jeepay-aba-channel/</link><guid isPermaLink="true">https://dr.free--china.com/posts/jeepay-aba-channel/</guid><description>Jeepay 是国内比较成熟的开源聚合支付系统，但它内置的通道全是国内的。这篇记录我怎么在不动核心的前提下，给它接一条 ABA Pay。</description><pubDate>Mon, 10 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://github.com/jeequan/jeepay&quot; target=&quot;_blank&quot;&gt;Jeepay&lt;/a&gt; 是一套面向互联网企业的开源支付系统，支持普通商户、服务商模式和多应用接入，Java + Spring Boot + Vue 的经典栈。它的通道抽象做得不错，但内置实现全是国内的——微信、支付宝、云闪付。&lt;/p&gt;
&lt;p&gt;我需要的是东南亚的 &lt;strong&gt;ABA Pay&lt;/strong&gt;，所以得自己接一条。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;先想清楚：改哪里，不改哪里&lt;a href=&quot;#先想清楚改哪里不改哪里&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;二开开源项目最容易犯的错，是图省事直接在核心流程里 &lt;code&gt;if (channel == &quot;ABA&quot;)&lt;/code&gt;。这么干第一次很快，但上游一发新版本你就再也合不回去了。&lt;/p&gt;&lt;p&gt;所以第一步是把边界划清楚：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;不动&lt;/strong&gt;：订单状态机、商户/应用体系、对账主流程、管理后台框架&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;只加&lt;/strong&gt;：一个新的通道实现，塞进 Jeepay 已有的通道 SPI 里&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Jeepay 的支付通道是按「一个通道 = 一组实现类」组织的，只要按它的接口把该实现的实现了，上层完全感知不到你是新加的。这就是它抽象做得好的地方。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;要实现的三件事&lt;a href=&quot;#要实现的三件事&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;一条支付通道能跑通，本质上只有三件事：&lt;/p&gt;&lt;p&gt;&lt;strong&gt;1. 下单&lt;/strong&gt; — 把 Jeepay 的统一订单参数翻译成渠道要的格式，调渠道接口，拿回一个可以给用户扫的二维码或跳转链接。这一步的难点通常在签名算法，每家都不一样。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;2. 异步回调&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;strong&gt;幂等&lt;/strong&gt;：渠道会重复推送，同一笔订单收到两次成功通知不能加两次钱&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;金额校验&lt;/strong&gt;：回调里的金额必须和本地订单金额一致才算数&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;3. 查单 / 对账&lt;/strong&gt; — 回调不是可靠的（网络抖动、你的服务重启都可能丢）。所以必须有一条主动查单的兜底路径，以及日终对账。&lt;strong&gt;只依赖回调的支付系统，迟早会丢单。&lt;/strong&gt;&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;关于「测试环境」&lt;a href=&quot;#关于测试环境&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;支付这块最麻烦的不是写代码，是&lt;strong&gt;没法随便测&lt;/strong&gt;。渠道的沙箱环境往往和生产行为不一致，而生产环境每测一笔都是真金白银。&lt;/p&gt;&lt;p&gt;我的做法是在通道实现和真实渠道之间放一层 bridge，本地开发时 bridge 指向一个可以手动构造各种回调（成功、失败、重复推送、金额不符）的桩服务。这样上面那三个必须做对的点，全都能在本地覆盖到。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;部署&lt;a href=&quot;#部署&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Docker Compose 起。仓库里维护了几套 compose 文件对应不同环境，这样本地、测试、生产之间的差异是显式写在文件里的，而不是靠某个人记得改哪个环境变量。&lt;/p&gt;&lt;hr /&gt;&lt;blockquote&gt;&lt;p&gt;支付相关的具体参数、密钥配置和渠道文档细节这里不展开。这篇主要想说的是&lt;strong&gt;二开的边界怎么划&lt;/strong&gt;——这个思路换到任何一个成熟开源项目上都适用。&lt;/p&gt;&lt;/blockquote&gt;&lt;/section&gt;</content:encoded></item></channel></rss>