一个人加 AI 用 66 天从空目录做到生产环境:P2P 内网穿透产品开发复盘
一个人 + AI:66 天,从空目录到生产环境 —— P2P 内网穿透产品开发复盘(附全自动编程方法论) - 吃西瓜的星星
作者用 AI 编码智能体在 66 天内完成开源 P2P 内网穿透产品 P2PSocket_AI,全程未手写业务代码,产出约 6.8 万行代码、995 项自动化测试和 193 次提交,并已部署生产。
2026-08-20,我建了一个空目录和一份 PRD;2026-10-25,这个项目在生产环境服役,TCP 打洞的新流程刚刚上线成交。全程我没有亲手写过一行业务代码——从协议字节到 SQL 迁移、从 Vue 页面到 systemd 沙箱,全部由 AI 编码智能体完成。本文复盘整个过程:项目是什么、怎么走过来的、现在跑成什么样,以及最重要的——怎么用 AI 跑通一个完整产品的"全自动编程"。
一、先说结果
- 193 次提交,66 天,五个里程碑全部收官:核心链路 → 打洞完整 → 管理后台 → 交付打包 → 安全加固。
- 约 6.8 万行代码(C# 5.2 万行 / 335 个文件 + 前端 1.5 万行 / 94 个文件),995 项自动化测试(后端 837 + 前端 158),编译 0 警告,CI 强制覆盖率门槛(Core 行覆盖 80%+,门槛 70%)。
- 已部署生产:一台 2C/2GB 的云服务器跑了服务器端,多台 Windows / Linux 客户端日常服役(远程桌面就走在自己这条隧道上)。
- 维护期靠实弹回流持续进化:最近两周从生产日志抓出并修复了两个 CGNAT 深水区缺陷,其中 TCP 打洞整段流程被推翻重设计,上线当天生产首连成交。
项目叫 P2PSocket_AI,已开源:https://github.com/bobowire/P2PSocket_AI 。它是我多年前开源项目 P2PSocket 的产品化重构——代码是全新的,经验是老项目攒下的,而这一次的写法完全不同。
二、这个项目是什么
一句话:把一台设备上的内网服务,通过 P2P 打洞直连隧道,暴露给另一台设备。
典型场景是远程桌面:公司电脑建立映射,回家访问 100.64.0.2:3588,流量走打洞直连隧道直达公司电脑的 3389 端口——不经第三方中转、端到端加密。类似的还有内网网站发布、SSH、NAS、数据库跨网互访。
访问方设备 A 服务端(公网部署) 服务方设备 B
┌──────────────┐ ┌───────────────┐ ┌──────────────┐
│ P2P.Client │◀─控制 7000/TCP─│ P2P.Server │◀─控制 7000/TCP─│ P2P.Client │
│ 虚拟网卡 │ STUN 3478 │ 注册/授权/信令 │ STUN 3478 │ 虚拟网卡 │
└──────┬───────┘ └───────────────┘ └──────┬───────┘
│ UDP/TCP 打洞 → 加密隧道直连(失败→自动回退中继 7010-7020) │
└──────────────────────────────────────────────────────────────────┘
本机应用连 100.64.0.2:本地端口 ──▶ 映射引擎 ──▶ 隧道 ──▶ 对端 127.0.0.1:目标端口
设计原则只有两条:控制面集中、数据面 P2P——公网服务器只做注册、信令、STUN 和打洞失败时的中继兜底,不做业务流量中转;全链路不依赖 TLS——隧道用 ECDH(P-256) + HKDF + AES-256-GCM 端到端加密,控制通道 HMAC 防重放,加密原语全部用 .NET 内置实现,零第三方加密依赖。
技术栈:.NET 10(ASP.NET Core Minimal API + Generic Host + Pipelines)、Vue 3 + TypeScript + Element Plus、SQLite + EF Core、MessagePack、自研 PCP 控制协议(7000/TCP)+ STUN(3478)、Windows Wintun / Linux TUN 虚拟网卡。
三、从 0 开始:动手写代码之前,先写了一堆文档
这是整篇文章最重要的一节。AI 编码的瓶颈从来不是"写不出代码",而是"不知道该写什么"。
很多朋友用 AI 写项目的方式是:开一个会话,描述需求,看 AI 生成,不满意再聊。这种方式写 demo 可以,写产品必死——因为每次会话 AI 都在"重新理解世界",你上一次口头达成的共识它不知道,需求含糊处它在替你做决定,而你甚至不知道它做了哪些决定。
我的做法是把传统开发中"程序员脑子里的隐性知识"全部显性化成三层文档:
- PRD(产品需求):功能需求逐条编号(FR-S 服务端 / FR-C 客户端),连安全需求(SEC)、非功能需求(NFR)、网络行为(NET)都独立编号。目前迭代到 v0.15。
- 技术设计(10 个分册):协议分册写到字节级——每条消息的 msgType、MessagePack 字段序号、错误码总表、加密握手时序、防重放窗口;此外还有数据模型、API 契约、前端路由、安全设计、构建交付、测试策略、追溯矩阵。目前修订到 v1.83。
- 任务清单(5 个里程碑,119 个编号任务):每个任务是一个可独立验收的交付单元,自带测试要求。
下面这份协议文档的精度,是"能跑测试向量"级别的——STUN 实现直接用 RFC 5769 官方测试向量做单元测试:
Core/Stun:RFC5389 Binding 子集 + XOR-MAPPED-ADDRESS(RFC5769 向量)+ DEVICE-AUTH 属性(M1-10,依据 02 §3.1/3.2、FR-S-603)
这是项目的第一个提交之一。因为"写什么"已经在文档里定死,AI 只需要回答"怎么写"。
于是第一天发生了什么?2026-08-20,16 个提交:九项目解决方案骨架、构建脚本 + CI、前端 workspace 骨架、统一加密封装(ECDH/HKDF/AES-GCM/HMAC/ECIES)、PCP 协议编解码(帧内 HMAC)、注册消息族、业务消息族、隧道协议(帧编解码 + 滑动窗口防重放 + 双重 ECDH 握手)、STUN 子集、数据库层(EF Core 11 张表 + WAL)、远程码生成、控制会话状态机、注册处理、用户能力模式——每一项都带单元测试。
这不是 AI 神奇,这是文档在神奇。你给 AI 一句模糊需求,它还你一个平均分的设计;你给它一份字节级协议,它还你一个能跑向量的实现。
四、开发过程:五个里程碑,越写越快
| 里程碑 | 时间 | 内容 | 任务数 |
|---|---|---|---|
| M1 核心链路 | 08-20 ~ 09-12(23 天) | 两台设备注册 + 第一条 UDP 直连映射端到端跑通 | 37 |
| M2 打洞完整与授权闭环 | 09-12 ~ 09-30(18 天) | TCP 打洞、中继回退、分组/远程码/白名单、UDP 映射、密钥轮换、网卡自愈 | 38 |
| M3 管理面与可观测 | 09-30 ~ 10-07(7 天) | 服务端 Web 管理后台全功能 | 18 |
| M4 交付打磨 | 10-07 ~ 10-11(4 天) | Windows 安装包、Linux deb/rpm、Docker 镜像、基准报告、随版手册 | 10 |
| M5 安全加固 | 10-22 ~ 10-24(3 天) | 3 个 P0 修复 + 告警/安全中心/IP 黑名单 + 平台加固 | 16 |
(M2/M3 各剩两三个需要特定实机环境的手工验收项,不阻塞主线;提交记录也看得出这不是全职投入,中间有不少空档。)
越写越快不是错觉:M1 平均 0.6 天一个任务,M5 平均 0.2 天。原因是文档、测试和代码模式都在复利——后面每个任务都是在"收敛",不是在"探险"。
挑两个里程碑里的关键设计展开讲讲。
M1:造了一个"假互联网"
测试打洞最大的难题是:CI 里没有 NAT。总不能每次跑测试都租两条不同运营商的宽带。
解决方案是 NatSimulator——一个单实例扮演"整个互联网 + 全部客户端 NAT"的模拟器:它持有全部"公网"套接字,内置 FullCone / RestrictedCone / PortRestricted / Symmetric 四种 NAT 模式(外加两种封锁模式),内嵌 STUN 代理按事务改写 XOR-MAPPED-ADDRESS,入站过滤行为严格按 RFC 定义实现。上千项测试全部在本地回环离线、确定性、可重复地跑。
这个装置成了整个项目的信任基石:后来它长出了 47 格的"打洞成功率矩阵"基准(5 种 UDP NAT 两两组合 + TCP 模式 × 并发路数),打洞算法每次改动都在这个矩阵上验证。
M5:3 天 16 项任务的安全加固
M5 的输入是一次全面安全评估,回流了 3 个 P0:
- 登录密码明文传输(协议层历史遗留)→ ECIES 加密硬切。部署完成后我用 tcpdump 在公网抓包留证:修复前登录帧里密码字段是 65 字节明文,修复后是 102 字节 ECIES 密文,帧内唯一可读的 ASCII 只剩用户名。
- 注册与登录无防滥用 → 注册三重闸门(开关 / 单 IP 令牌桶 / 设备总量)+ 登录防爆破(账户、IP 双维指数延迟,四入口统一)。
- 平台面 → IP 黑名单四面拦截 + 自动封禁、安全事件 webhook 告警、管理端安全中心、设备凭据落库加密、systemd 最小权限沙箱(非 root +
ProtectSystem=strict,全文件系统只读、白名单唯二可写)、升级产物 SHA-256 清单。
16 项任务,3 天,全部带测试和文档回写。
五、现在达到了什么效果
工程面:编译 0 警告 0 错误;后端 837 项测试 + 前端 158 项测试全绿;Core 库行覆盖 80%+(CI 解析 cobertura 报告强制 70% 门槛——顺带一提,coverlet 的阈值参数实测并不拦截,只能自己解析,这本身就是个值得单独写一篇的坑);45 份 Markdown 文档与代码同步演进。
性能面(自建七段基准 harness,每格独立世界、两轮一致性校验):
- 打洞直连建立耗时 p50 = 219ms(生产实机实测 192ms,互相印证);中继回退约 10.2s(含 10s 打洞预算的固有成本,可配置权衡)。
- 4 流吞吐约 200Mbps,瓶颈分析结论:在端侧全栈加密分帧,而不是中继路径(服务端 8 字节头零解密转发不构成瓶颈)。
- RTT 附加开销:直连 +0.22ms,中继再 +0.04ms——相对真实网络几十 ms 的 RTT 可以忽略。
- 500 设备注册压测:稳态 CPU 0.7%、内存 236MB(2C/2GB 机器)——一台最低配 VPS 就能服务一个小型团队。
生产面:服务器上线以来持续服役,抽样 10 天窗口统计到 2465 条打洞记录,当前版本零中继失败。直连占比只有 0.53%?这是部署拓扑的必然而非缺陷:家宽出口是移动 CGNAT,云服务器安全组挡掉随机打洞端口,中继就是这个拓扑下的常态承载;cone×cone 组合按矩阵应当直连。管理后台只绑回环,外部端口扫描实证 7500 不可达。
维护期的两个真实故事(说明这个系统交付后还在进化):
- 某设备升级后打洞全灭 + 中继也失败。两侧日志对出两层根因:打洞腿是出口 NAT 换成了移动 CGNAT,属预期内的中继回退场景;但中继腿暴露真缺陷——CGNAT 对中继 TCP 端口是 DROP 型封锁(不是 RST),旧代码的异常过滤器只接 IOException/SocketException,10 秒超时抛出的取消异常穿透过滤器,导致 UDP 兜底永远不会触发。修复只有一行语义:超时也是"承载不可用",转 UDP。修复前用新测试复现失败,修复后命中——红绿实证。
- TCP 打洞旧流程靠"端口预测":探测后推测对端将分配的端口再去连。实弹证明它在 CGNAT 时序扰动下脆弱——出口 NAT 对预测端口主动 RST,12 波齐射全灭。于是整段流程推翻重设计为"晚探测":双端先经 STUN-TCP 交换拿到对端实测端点作开火锚点,替代推测,再扇形齐射。配套的 11 个集成场景按新的扰动代数重写——重写前 11/11 确定性失败、重写后 11/11 绿,上线当天生产首连成交。
六、方法论:怎么用 AI 跑通"全自动编程"
先定义清楚我说的"全自动":人不写代码,人的输出是需求、决策和验收;从需求到提交的全部代码由 AI 完成。 不是"AI 补全代码我缝合",也不是"AI 出方案我把关每一行"。以下八条是我用 119 个任务验证过的做法,按重要性排序。
1. 文档先行,给 AI 一份"可执行的需求"
PRD → 技术设计 → 任务清单,三级缺一不可。协议、存储结构、API 形状、错误码全部定案到字节/字段级。这份文档同时是给 AI 的"外部记忆"——任何一次新会话,AI 的启动动作都是"读最小必读集",而不是靠你复述上下文。工具叫什么不重要,各家命令行 Agent 都行,重要的是工作流。
2. 一切编号化,让每个行为可追溯
需求 FR、技术决策 TD、未决问题 OQ、安全 SEC……每个行为都有编号出处,提交信息强制携带:
[Server] Feat:中继服务双承载与 0x74 分配闭环(M2-07,依据 02 §6、05 §6、FR-S-701/704、TD-11)
这不只是审计好看。AI 在实现时能精确引用设计原文,而不是"自由发挥";出问题时你能沿编号在 30 秒内定位到是哪条需求、哪次决策。
3. 给 AI 立规矩:把"已知失效模式"当安全漏洞来防
我写了 34 条编号规则(AI-01 ~ AI-34),每条针对一类真实翻车过的 AI 失效模式:
- 防幻觉:不确定的 API 先查证再写,禁止凭记忆臆造方法签名;P/Invoke 逐参数对照官方头文件。
- 防镀金:第三方依赖白名单制,新增任何 NuGet/npm 包 = 停下上报;用户亲自定过的参数原样实现,禁止"优化"——这条至关重要,AI 特别喜欢"顺手帮你优化"一个你已经权衡过的参数。
- 防漂移:术语 → 代码标识符对照表,连"禁止的同义词"都写明(比如远程码只许叫
remoteCode,不许叫 code/token/pin);协议字段、表结构列、API 字段是同一实体的三个投影,改任何一处必查其余两处。 - 防撒谎:未完成就说未完成;测试失败必须带原始输出;禁止用"理论上可以"冒充已验证。
- 防作弊:禁止修改断言迁就实现;禁止用 TODO / 占位实现冒充完成。
4. OQ 机制:AI 的"不确定"必须有出口
文档有缺口或矛盾时,唯一正确的动作是:停任务 → 登记未决问题(附两处出处原文)→ 人做决议 → 决议编号化回填文档 → 继续干。AI 无权仲裁设计矛盾——我曾真实翻过车:两处各自自洽的设计互相矛盾,三轮审查才抓出来 13 项。此后这成了铁律。
整个项目累计 22 个 OQ。人只做选择题,AI 负责把选择题出清楚(附每个选项的代价分析)。失控的 AI 在猜,受控的 AI 在问——这就是"全自动"和"翻车"的分界线。
5. 任务粒度 = 一次可评审交付,交付前过十项自检
每个任务自带测试、可独立验收;完成前逐项过清单:
[ ] 1. 每个改动都有编号依据
[ ] 2. 编译零错误,新代码不留新警告
[ ] 3. 测试全过,失败项如实列出
[ ] 4. 动了消息/表列/API 字段:三视图三处已核对
[ ] 5. 改名/删除:旧名+同义词 全库 grep 无漏改
[ ] 6. 改变设计语义:文档+修订记录+追溯矩阵三处回写
[ ] 7. 无秘密进日志
[ ] 8. 无白名单外新依赖
[ ] 9. 并发纪律符合约定
[ ] 10. 新文件落在规范目录
任何一项不过 = 任务未完成。AI 的产出以提交为单位沉淀,而不是聊天记录——每个提交都是完整、可回滚、可追溯的单元。
6. 测试是信任锚:把"不可测"变成"可测"
NatSimulator 把打洞这个"没法测"的问题变成离线确定性测试;覆盖率门槛进 CI;flaky 不当作环境问题而是当作缺陷——9 个不稳定测试家族,逐一用测试结果文件取证定位根因(包括一个很典型的:CI 只有 2 核,同步 SQLite I/O 阻塞线程池 → 异步续体排队 → 整窗停顿,本地多核从不复现)。
关键纪律是红绿实证:修复前必须先有稳定失败。重写 11 个打洞场景时,先证明它们 11/11 确定性失败,重写后 11/11 绿——这样"测试有效"才不是自欺。
7. 生产反馈闭环:让实弹给 AI 出题
上线不是终点。生产日志、服务端统计、必要时的抓包取证是需求的来源;缺陷进台账清单;修复必须带红绿测试;发布前回滚件先备份。第五节那两个 CGNAT 故事就是这条闭环跑出来的——而且我观察到一个反直觉的现象:AI 非常擅长修这类"带完整证据链的复杂缺陷"。两侧日志对照 → 定位两层根因 → 一处修复共用入口 → 红绿验证 → 文档回写,人做要几天,AI 一个晚上。
8. 人的角色:从"写代码的"变成"出题和验收的"
把上面七条合起来,人在这个流程里实际承担四件事:写需求(文档)、做决策(OQ 拍板、参数定夺)、验收(看 diff、看测试报告)、喂实弹(生产反馈)。代码这件事本身,人退出了。
七、成本与不够浪漫的部分
说实话的部分:
- 前期投入很重。第一周几乎没有"产出"——全在写 PRD 和设计。如果只做一个周末 demo,这套流程是杀鸡用牛刀;它从第二个里程碑开始回本,越往后越赚。
- 验收没有消失,变形了。每个任务我都要看 diff、看自检报告、拍板 OQ。我更像这个项目的架构师 + Tech Lead + QA,AI 是那个读文档极快、从不遗忘、可以无限并行的实现工程师——但你不能不看就签收,AI 的自信程度和它的正确程度是两个独立变量。
- 上下文管理是真实的坑。大仓库长会话必漂移,解法不是把一切塞进上下文,而是"编号引用 + 最小必读集"——让 AI 随时能精确取回它需要的哪一小份设计,而不是背着全部历史。
- 不同任务的成功率差异很大。网络时序、协议字节、并发竞态这类"逻辑刚性问题",AI 配上模拟器和测试代数后做得比大多数人好;而 UI 审美、文案措辞这类"感受型问题",它需要你给出明确的评估标准和分批批复,否则它会在"你觉得不对但说不清哪不对"的地方空转。
八、写在最后
回头看,这套方法论的内核其实一句话:把工程纪律做成 AI 能执行的形态。文档让 AI 不漂移,编号让历史可追溯,规则防住已知的失效模式,测试让改动不回归,OQ 让不确定有出口——这些本来就是好工程该有的东西,只是过去它们靠人的自觉和记忆,现在它们变成了流程里强制的一环。
AI 没有替代我,它把我从打字员的位置上解放出来,还给了我一间以前雇不起的实现团队。
项目已开源,欢迎围观、试用、拍砖:
- 本项目:https://github.com/bobowire/P2PSocket_AI (含全部文档目录,PRD / 技术设计 / 开发规范 / 任务清单都在仓库里,方法论可以直接抄作业)
- 原版开源项目(致敬起点):https://github.com/bobowire/Wireboy.Socket.P2PSocket
- QQ 交流群:417159195(与原项目同群)
如果你也在用 AI 做完整项目,欢迎在评论区交流你踩的坑。
来源:博客园 · cnblogs.com