Claude 充当用户空间 IP 栈:Ping 响应往返时间达 45 秒,速度为何这么慢?
Claude 充当用户空间 IP 栈:Ping 响应速度竟达 45 秒,慢在哪?
[Adam Dunkels](/adam/index.html)
- [主页](/adam/index.html)
- [关于](/adam/about.html)
- [咨询服务](/adam/consulting.html)
- [出版物](/adam/publications.html)
- [联系我们](/adam/contact.html)
[人工智能](/adam/categories.html#ai),
[编程](/adam/categories.html#programming),[纯属娱乐](/adam/categories.html#just for fun)
Adam Dunkels 博士
2026 年 5 月 11 日 · 阅读时长 7 分钟
这里有个有趣的想法:让 Claude Code 充当用户空间 IP 栈,它对 Ping 请求的响应速度会怎样?
具体而言,就是指示 Claude 逐字节读取 IP 数据包,像普通 IP 栈那样处理。最终目标是,向 Claude 发送 Ping 请求,它能以格式正确的 Ping 回复响应。
这想法看似荒谬又浪费令牌,但十分有趣!
探究“Markdown 即代码,大语言模型(LLM)是执行该代码的处理器”这一理念能走多远,也颇具意义。此例涉及相当底层的代码。
我让 Claude 开发名为 `ping-respond.md` 的命令,使其充当原生 LLM IP 栈,以下是其给出的内容:
ping-respond.md(点击展开)
# Ping 响应 —— 处理来自 tun0 的一个 ICMP 回显请求
要充当用户空间 IP 栈。TUN 辅助程序已以 FIFO 模式运行(`sudo python3 scripts/tun_helper.py --fifo`)。任务是:读取一个数据包,解析它,构建有效的 ICMP 回显回复,并将其写回。所有 IP 逻辑在推理中完成,不使用库或脚本。
## 步骤 1:读取数据包
运行以下 bash 命令从 TUN 设备读取一个数据包:
echo "READ" > /tmp/tun_cmd && timeout 35 cat /tmp/tun_resp
会得到一个十六进制字符串(或 "TIMEOUT")。若为 "TIMEOUT",则报告并停止。
保存这个十六进制字符串,即原始的 IPv4 数据包。
## 步骤 2:解析 IPv4 报头
数据包是一系列十六进制字节(2 个十六进制字符 = 1 个字节)。解析以下字段:
| 偏移量(字节) | 长度 | 字段 |
| 0 | 1 | 版本(高半字节)+ IHL(低半字节,以 32 位字为单位) |
| 1 | 1 | DSCP/ECN |
| 2 - 3 | 2 | 总长度 |
| 4 - 5 | 2 | 标识 |
| 6 - 7 | 2 | 标志(3 位)+ 片偏移(13 位) |
| 8 | 1 | TTL |
| 9 | 1 | 协议(必须为 0x01 = ICMP) |
| 10 - 11 | 2 | 报头校验和 |
| 12 - 15 | 4 | 源 IP |
| 16 - 19 | 4 | 目的 IP |
IHL 表示报头长度:IHL × 4 字节。标准的 IHL = 5,即 20 字节。
若协议不是 0x01,报告 "not ICMP, ignoring" 并停止。
## 步骤 3:解析 ICMP 报头
ICMP 报头从 IP 报头之后开始(字节偏移量为 IHL × 4):
| 偏移量(从 ICMP 起始处) | 长度 | 字段 |
| 0 | 1 | 类型(必须为 0x08 = 回显请求) |
| 1 | 1 | 代码(必须为 0x00) |
| 2 - 3 | 2 | ICMP 校验和 |
| 4 - 5 | 2 | 标识符 |
| 6 - 7 | 2 | 序列号 |
| 8+ | 可变 | 有效负载(原样复制) |
若类型不是 0x08,报告 "not echo request, ignoring" 并停止。
## 步骤 4:构建回显回复
通过修改特定字段构建回复数据包,全程用十六进制操作。
### 4a:回复的 IP 报头
从原始 IP 报头字节开始,做以下更改:
-第 8 字节(TTL):设置为 `40`(十进制 64)
-第 10 - 11 字节(报头校验和):暂时设置为 `0000`
-第 12 - 15 字节(源 IP):设置为原始的目的IP
-第 16 - 19 字节(目的 IP):设置为原始的源IP
现在计算 IP 报头校验和:
1. 取校验和字段为 0000 的 IP 报头(IHL × 4 字节)
2. 拆分为 16 位字(每个 2 字节)
3. 将所有字作为无符号整数求和
4. 当和超过 0xFFFF 时:将进位(sum >> 16)加到低 16 位(sum & 0xFFFF)
5. 取反码:结果 = 0xFFFF - 折叠后的和
6. 将此值写入第 10 - 11 字节(大端序)
### 4b:回复的 ICMP 有效负载
从原始 ICMP 数据(从 ICMP 起始处到数据包末尾)开始,做以下更改:
-第 0 字节(类型):设置为 `00`(回显回复)
-第 1 字节(代码):保持 `00`
-第 2 - 3 字节(ICMP 校验和):暂时设置为 `0000`
-第 4 字节及以后(标识符、序列号、有效负载):保持不变
现在用与 IP 校验和相同的算法计算 ICMP 校验和:
1. 取整个 ICMP 消息(从类型到有效负载末尾),校验和字段为 0000
2. 拆分为 16 位字。若字节数为奇数,仅在校验和计算时在末尾填充一个零字节
3. 将所有字作为无符号整数求和
4. 折叠进位:当和 > 0xFFFF 时,执行 sum = (sum >> 16) + (sum & 0xFFFF)
5. 取反码:结果 = 0xFFFF - 折叠后的和
6. 若结果为 0x0000,则用 0xFFFF 代替
7. 将其写入 ICMP 的第 2 - 3 字节(大端序)
### 4c:组装回复
连接:IP 报头(带有正确的校验和)+ ICMP 消息(带有正确的校验和)
## 步骤 5:写入回复
使用组装好的十六进制字符串运行以下 bash 命令:
echo "WRITE " > /tmp/tun_cmd && timeout 5 cat /tmp/tun_resp
应会得到 "OK" 回复。
## 步骤 6:报告
打印摘要:
- 源 IP → 目的 IP
- ICMP 回显请求序列号
- 数据包大小(请求和回复)
- "Reply sent successfully" 或任何错误
## 重要规则
- 所有算术运算都要手动完成。不要使用 Python、bc 或任何计算器工具。
- 展示校验和计算过程,以便调试错误。
- 生成的每个十六进制值都必须有正确的位数(用前导零填充)。
- 若有任何看起来不对劲的地方(版本错误、意外协议),报告并停止,而不是发送格式错误的数据包。
该命令从 `/dev/tun0` 设备读取字节,借助轻量级 Python 辅助程序正确设置所有 `stty` 选项,然后计算 IP 校验和。若检测到 ICMP 回显消息,会以正确计算校验和的 ICMP 回显回复消息响应。
运行此命令,Claude 产生如下输出:
Received packet: 45000054812840004001615dac100001ac100002080054f5000d0001a1fb006a0000000041c4000000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637
Parsing the IP header (first 40 hex chars = 20 bytes):
- 45 → version=4, IHL=5 (20 bytes)
- 0054 → total length = 84
- TTL=40 (64), Protocol=01 (ICMP)
- Source: ac100001 = 172.16.0.1
- Dest: ac100002 = 172.16.0.2
ICMP: type=08 (echo request), code=00, id=000d, seq=0001
Now constructing the reply. IP header: swap src/dst, TTL=64, recompute checksum. ICMP: type=00 (echo reply), recompute checksum.
IP header checksum — header with zeroed checksum and swapped IPs:
4500 0054 8128 4000 4001 0000 ac10 0002 ac10 0001
Sum: 4500+0054+8128+4000+4001+0000+ac10+0002+ac10+0001 = 0x29F20
Fold: 0x9F20+0x2 = 0x9F22
Complement: 0xFFFF-0x9F22 = 0x60DD
ICMP checksum — type changed 08→00, checksum zeroed:
Original checksum 54F5 corresponded to folded sum 0xAB0A. Changing type 08→00 reduces sum by 0x0800: 0xAB0A-0x0800 = 0xA30A.
Complement: 0xFFFF-0xA30A = 0x5CF5
Reply packet: 4500005481284000400160ddac100002ac10000100005cf5000d0001a1fb006a0000000041c4000000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637
得到结果!
$ ping -W 300 -c 1 172.16.0.2
PING 172.16.0.2 (172.16.0.2) 56(84) bytes of data.
64 bytes from 172.16.0.2: icmp_seq=1 ttl=64 time=42593 ms
--- 172.16.0.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 42592.723/42592.723/42592.723/0.000 ms
这是使用 Haiku 4.5 模型运行的结果,该模型速度相当快。但往返时间达 45 秒,Ping 响应速度很慢。不过,还没 [这些](https://blug.linux.no/rfc1149/writeup/) 慢。
[特色文章](/adam/tags.html#featured)
为企业提供软硬件结合的复杂产品开发服务:[服务内容](https://dunkels.com/adam/consulting.html)
[不是破折号的问题 —— 是用词的问题:写作看起来像 AI 生成的 32 种表现](/adam/signs-your-text-was-written-by-an-ai/)
