<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Zhouxing Fu</title><description>Finance, data, quant systems, and the engineering notes behind them.</description><link>https://blog.fuzhx.com/</link><language>zh_CN</language><item><title>从 iNode 到 systemd：我如何指挥 Codex 处理一次真实网络排障</title><link>https://blog.fuzhx.com/posts/codex-sufe-linux-8021x/</link><guid isPermaLink="true">https://blog.fuzhx.com/posts/codex-sufe-linux-8021x/</guid><description>一次把校园网 802.1X 认证、DHCP、路由、DNS 和 systemd 自启动收束成可重启恢复系统服务的 Codex 协作记录。</description><pubDate>Sat, 13 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;从 iNode 到 systemd：我如何指挥 Codex 处理一次真实网络排障&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;Written with Codex.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这不是一篇“让 AI 帮我修好了网络”的故事。&lt;/p&gt;
&lt;p&gt;更准确地说，这是一次我和 Codex 分工处理复杂现场问题的实践：我负责目标、边界、硬件、风险判断和现场动作；Codex 负责把问题拆开、设计验证、执行命令、读日志、改脚本，再把结果收束成可重启恢复的系统服务。&lt;/p&gt;
&lt;p&gt;最后的结果是，一台没有桌面环境的 Maxtang/N100 小主机，运行 Ubuntu Server 24.04，可以直接接入校园有线网。802.1X 认证、DHCP、路由、DNS、systemd 自启动和远程管理都跑通了。&lt;/p&gt;
&lt;p&gt;但这篇文章真正想写的不是 EAP Type 7，也不是某个脚本怎么拼 payload。那些只是问题表面。真正有意思的是：当现实世界里有网线、交换机、Windows 客户端、校园网策略、SSH 风险和一台裸服务器时，人应该怎样引导 Codex 做事。&lt;/p&gt;
&lt;h2&gt;先搭一条不会死的路&lt;/h2&gt;
&lt;p&gt;我一开始的目标很简单：N100 不装桌面，不装 Windows，只作为长期运行的 Ubuntu Server。&lt;/p&gt;
&lt;p&gt;问题也很直接：学校有线网使用 H3C/iNode 客户端认证，网络中心明确说不支持 Linux 客户端。Windows 上可以点 iNode，Ubuntu Server 上没有这个按钮。&lt;/p&gt;
&lt;p&gt;这时最容易犯的错，是急着让 Codex 开始“破解”校园网认证。&lt;/p&gt;
&lt;p&gt;Codex 没有这么做。它先要求我建立一条救命管理链路。&lt;/p&gt;
&lt;p&gt;最终现场是这样：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;R7000 笔记本 Wi-Fi 上网
R7000 有线口直连 N100 的 enp2s0
Windows ICS 提供 192.168.137.0/24
N100 固定为 192.168.137.2
N100 的 enp1s0 再接校园墙口做实验
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这一步不性感，但它决定了后面能不能安全试错。&lt;/p&gt;
&lt;p&gt;如果没有这条管理线，每次改路由、重启网络服务、测试 DHCP 都可能把自己锁在机器前。Codex 能做很多事，但它不能替我把网线插回去，也不能在 SSH 断掉以后凭空继续操作。&lt;/p&gt;
&lt;p&gt;所以第一件事不是写脚本，而是给 Codex 一个不会让它失明的现场。&lt;/p&gt;
&lt;h2&gt;人负责边界，Codex 负责收敛&lt;/h2&gt;
&lt;p&gt;这次排障里，我最深的感受是：人不需要亲手做每个技术动作，但必须知道 Codex 解决问题真正需要什么。&lt;/p&gt;
&lt;p&gt;它需要稳定的控制通道。&lt;/p&gt;
&lt;p&gt;它需要清楚的接口角色。&lt;/p&gt;
&lt;p&gt;它需要命令输出、抓包、日志、路由表、服务状态，而不是“好像不通”“应该是这个口”。&lt;/p&gt;
&lt;p&gt;它还需要明确的约束：什么可以动，什么不能动；什么能重启，什么要先确认；真实账号、密码、MAC、pcap 不能进公开仓库。&lt;/p&gt;
&lt;p&gt;我给 Codex 的不是“帮我联网”这类模糊愿望，而是一组现场条件：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;enp2s0&lt;/code&gt; 是管理口，必须保 SSH。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;enp1s0&lt;/code&gt; 是校园口，允许实验。&lt;/li&gt;
&lt;li&gt;默认路由不能随便被校园口抢走。&lt;/li&gt;
&lt;li&gt;任何可能断开 R7000、Codex 或 N100 SSH 的操作，都要先停下来确认。&lt;/li&gt;
&lt;li&gt;账号、密码、MAC 只在本机私有配置里使用。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;有了这些边界，Codex 才能大胆地做执行工作。&lt;/p&gt;
&lt;p&gt;它会先只读检查，再小步修改。它会在每次行动前说明影响范围。它会在命令超时后回头确认状态，而不是猜“应该成功了”。它会把失败当成证据，而不是当成挫败。&lt;/p&gt;
&lt;p&gt;这才是我觉得 Codex 最有价值的地方。&lt;/p&gt;
&lt;h2&gt;抓包终止了猜测&lt;/h2&gt;
&lt;p&gt;校园网认证一开始有很多可能方向。&lt;/p&gt;
&lt;p&gt;也许是普通 PEAP/MSCHAPv2？也许 &lt;code&gt;wpa_supplicant&lt;/code&gt; 写个配置就行？也许某个开源 H3C 客户端能直接用？&lt;/p&gt;
&lt;p&gt;Codex 没有停在这些猜测上。它让我先做被动抓包，再做受控主动探测。校园口不拿 IP，不改默认路由，只看二层发生了什么。&lt;/p&gt;
&lt;p&gt;第一次被动抓包几乎没有东西。主动发 DHCP 只有 Discover，没有 Offer。然后主动发 EAPOL-Start，交换机终于返回了 Identity 请求。继续回应 Identity 后，关键包出现了：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;EAP Request Identity
EAP Response Identity
EAP Request Type 7
EAP Response Type 7
EAP Success / Failure
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这一步把方向定死了：不是普通 PEAP/MSCHAPv2，而是 iNode/H3C 的 Type 7 流程。&lt;/p&gt;
&lt;p&gt;后面 Codex 拉了几个开源实现做静态分析，也尝试了低风险握手。但通用实现都失败了。它没有继续撞真实账号，而是要求我回到 Windows iNode，抓一次成功认证包。&lt;/p&gt;
&lt;p&gt;这里的分工很典型。&lt;/p&gt;
&lt;p&gt;Codex 能告诉我应该抓什么、怎么抓、哪些字段关键、哪些工具没用。比如 Charles 抓不到 EAPOL，因为那是二层帧，不是 HTTP 流量。&lt;/p&gt;
&lt;p&gt;但我必须提供硬件现场：把 R7000 的网线从 N100 拔下来，接到校园墙口；关闭 ICS，让 Windows 有线口恢复普通 DHCP；启动 iNode；认证成功后再把线切回 N100。&lt;/p&gt;
&lt;p&gt;Codex 负责看包，我负责让它看得到包。&lt;/p&gt;
&lt;h2&gt;误判不断出现，但都被证据拉回来&lt;/h2&gt;
&lt;p&gt;这次过程里出现过很多看起来合理的误判。&lt;/p&gt;
&lt;p&gt;比如最初 Windows iNode 也认证失败，很容易以为是 Type 7 算法不对。后来抓包和日志说明，问题更像是有线账号的 MAC 绑定不匹配。协议走到了 Type 7，但服务器直接回 &lt;code&gt;EAP Failure&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;比如 N100 上 &lt;code&gt;ping 192.168.137.1&lt;/code&gt; 不通，也容易以为 R7000 管理线没通。Codex 从 R7000 侧反向测试，发现 &lt;code&gt;192.168.137.2&lt;/code&gt; 能 ping，ARP 也解析到了 N100 的 MAC，22 端口也开着。最后判断只是 Windows 防火墙不回 ICMP。&lt;/p&gt;
&lt;p&gt;比如我一度怀疑 BBR3 导致网络异常。Codex 先看内核参数，发现当时拥塞控制还是 &lt;code&gt;cubic&lt;/code&gt;，可用算法里也没有 BBR。更关键的是，BBR 只影响已有 IP 连通之后的 TCP 拥塞控制，管不到 EAPOL、DHCP、ARP。&lt;/p&gt;
&lt;p&gt;这些场景让我意识到：复杂排障里，最危险的不是不知道，而是太快相信一个顺耳的解释。&lt;/p&gt;
&lt;p&gt;Codex 的价值不是永远正确，而是它会持续把解释拉回可验证证据。&lt;/p&gt;
&lt;h2&gt;从“跑通一次”到“重启后还在”&lt;/h2&gt;
&lt;p&gt;第一次拿到 &lt;code&gt;EAP Success&lt;/code&gt; 时，其实还远远没结束。&lt;/p&gt;
&lt;p&gt;认证成功之后，要 DHCP。DHCP 成功之后，要路由。路由正确之后，要 DNS。DNS 正常之后，还要 systemd 重启后自动恢复。&lt;/p&gt;
&lt;p&gt;更麻烦的是，校园交换机会周期性发起身份检查。我们最初的脚本可以认证成功，但它每隔一段时间主动发 &lt;code&gt;EAPOL-Start&lt;/code&gt;，反而和交换机自己的保活流程撞车。结果就是过一会儿收到 &lt;code&gt;EAP Failure&lt;/code&gt;，链路又掉了。&lt;/p&gt;
&lt;p&gt;最后稳定下来的策略很克制：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;未认证时，每 5 秒重试 &lt;code&gt;EAPOL-Start&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;认证成功后，停止主动 Start。&lt;/li&gt;
&lt;li&gt;平时只响应交换机发来的 Identity 和 Type 7。&lt;/li&gt;
&lt;li&gt;收到 Failure 后，回到未认证状态重新开始。&lt;/li&gt;
&lt;li&gt;认证成功后写入 &lt;code&gt;/run/sufe-8021x-authenticated&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;DHCP 服务等待这个状态文件，而不是赌一个固定 sleep。&lt;/li&gt;
&lt;li&gt;DHCP 拿不到租约时干净失败，不继续写错误默认路由。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这不是“AI 一次性生成了完美脚本”。&lt;/p&gt;
&lt;p&gt;真实过程是：跑通，重启，失败；看日志，改状态机；再重启，再观察；发现周期性 Failure，再抓包；改 EAPOL-Start 策略；最后等待 90 秒、再重启验证。&lt;/p&gt;
&lt;p&gt;Codex 在这里像一个有耐心的工程同事。它不嫌烦，也不会因为“刚才成功过”就提前宣布结束。&lt;/p&gt;
&lt;h2&gt;我真正做了什么&lt;/h2&gt;
&lt;p&gt;如果把这次实践简化成“Codex 写了一个 802.1X 脚本”，那就漏掉了大半价值。&lt;/p&gt;
&lt;p&gt;我真正做的是现场总控。&lt;/p&gt;
&lt;p&gt;我准备了 R7000、N100、两根网线、显示器键盘、Windows iNode、Wireshark/tshark、校园墙口和可用账号。&lt;/p&gt;
&lt;p&gt;我在关键时刻换线、开关 ICS、关闭 TUN、输入 sudo 密码、确认 UAC、决定是否重启、判断能不能临时伪装授权 MAC。&lt;/p&gt;
&lt;p&gt;我也负责不断提醒边界：不要断 SSH，不要暴露服务，不要把真实账号密码写进仓库，不要为了方便把服务器直接裸露到校园网。&lt;/p&gt;
&lt;p&gt;这些事听起来不如写代码酷，但它们正是 Codex 做好工作的前提。&lt;/p&gt;
&lt;p&gt;Codex 能把排障步骤推进得很快，前提是我能提供一个可操作、可观测、可回滚的环境。&lt;/p&gt;
&lt;h2&gt;我不需要做什么&lt;/h2&gt;
&lt;p&gt;我不需要从头背 802.1X 协议。&lt;/p&gt;
&lt;p&gt;我不需要手动比较每个 EAP payload。&lt;/p&gt;
&lt;p&gt;我不需要自己去读一堆 H3C 开源客户端源码。&lt;/p&gt;
&lt;p&gt;我也不需要把每条 &lt;code&gt;ip route&lt;/code&gt;、&lt;code&gt;resolvectl&lt;/code&gt;、&lt;code&gt;tcpdump&lt;/code&gt; 命令都记下来。&lt;/p&gt;
&lt;p&gt;这些工作交给 Codex 就行。&lt;/p&gt;
&lt;p&gt;人的精力更应该放在判断上：现在缺的是抓包，还是日志？是认证没过，还是 DHCP 没来？是校园口问题，还是 R7000 ICS 问题？这个改动会不会断掉管理线？这个结论有没有被重启验证过？&lt;/p&gt;
&lt;p&gt;当我把问题问清楚，把现场搭好，把边界说清楚，Codex 就能承担大量具体劳动。&lt;/p&gt;
&lt;h2&gt;最后跑起来的样子&lt;/h2&gt;
&lt;p&gt;最终重启后，网络形态稳定成这样：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sufe-8021x.service active/running
sufe-campus-dhcp.service active/exited
enp1s0 10.x.x.x/xx
enp2s0 192.168.137.2/24
default via campus-gateway dev enp1s0 metric 50
default via management-gateway dev enp2s0 metric 500
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;校园口负责主出口。R7000 管理口保留为低优先级备用。Tailscale 可用后，甚至可以拔掉 R7000 管理线，用 Tailscale IP 直接 SSH。&lt;/p&gt;
&lt;p&gt;同时，校园网口没有暴露 SSH、1Panel、Jellyfin、Immich 等服务。管理入口保留在可信管理网和 Tailscale 上。&lt;/p&gt;
&lt;p&gt;这台 N100 从一台“没有桌面、没有校园网客户端、随时可能失联”的裸 Ubuntu Server，变成了一台可以继续部署服务的实体服务器。&lt;/p&gt;
&lt;h2&gt;这次经历给我的方法论&lt;/h2&gt;
&lt;p&gt;以后我再让 Codex 处理类似问题，会先问自己几个问题。&lt;/p&gt;
&lt;p&gt;我有没有给它一条不会断的控制通道？&lt;/p&gt;
&lt;p&gt;我有没有把实验面和管理面隔离开？&lt;/p&gt;
&lt;p&gt;我有没有把目标拆成可验证的小阶段？&lt;/p&gt;
&lt;p&gt;我给它的是现象描述，还是足够的证据？&lt;/p&gt;
&lt;p&gt;每个修复有没有清晰的回滚方式？&lt;/p&gt;
&lt;p&gt;最后有没有从干净重启状态验证？&lt;/p&gt;
&lt;p&gt;这套方法不只适用于校园网，也适用于很多现实世界里的系统问题。&lt;/p&gt;
&lt;p&gt;人不必和 Codex 抢具体执行权。更有效的分工是：人负责统筹、边界、现场资源和最终判断；Codex 负责持续执行、验证、记录和收敛。&lt;/p&gt;
&lt;p&gt;当问题足够复杂时，真正重要的不是“AI 会不会某个命令”，而是你能不能把现实世界组织成它可以工作的样子。&lt;/p&gt;
&lt;h2&gt;代码和文档&lt;/h2&gt;
&lt;p&gt;公共脚本和操作指南整理在这个仓库里：&lt;a href=&quot;https://github.com/K1ndredzzz/sufe-linux-8021x&quot;&gt;K1ndredzzz/sufe-linux-8021x&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;真实账号、密码、绑定 MAC、原始 pcap 和 iNode 日志不会进入仓库。&lt;/p&gt;
&lt;p&gt;仓库里保留的是可复用的部分：最小 Type 7 认证脚本、DHCP/路由脚本、systemd 单元、排障手册和抓包分析笔记。&lt;/p&gt;
&lt;p&gt;如果以后重启后断网，我不会再从头猜。先看管理口 SSH 是否还在，再重启两项服务：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl restart sufe-8021x.service
sudo systemctl restart sufe-campus-dhcp.service
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后看服务状态、地址、路由和 DNS。复杂问题最后能变成这几条命令，才算真正被收束过。&lt;/p&gt;
</content:encoded></item></channel></rss>