Claude 充当用户空间 IP 栈:Ping 响应往返时间达 45 秒,速度为何这么慢?

📅 2026/7/14 17:48:02 👁️ 阅读次数 📝 编程学习
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 个字节)。解析以下字段:

偏移量(字节)长度字段
01版本(高半字节)+ IHL(低半字节,以 32 位字为单位)
11DSCP/ECN
2 - 32总长度
4 - 52标识
6 - 72标志(3 位)+ 片偏移(13 位)
81TTL
91协议(必须为 0x01 = ICMP)
10 - 112报头校验和
12 - 154源 IP
16 - 194目的 IP

IHL 表示报头长度:IHL × 4 字节。标准的 IHL = 5,即 20 字节。

若协议不是 0x01,报告 "not ICMP, ignoring" 并停止。

## 步骤 3:解析 ICMP 报头

ICMP 报头从 IP 报头之后开始(字节偏移量为 IHL × 4):

偏移量(从 ICMP 起始处)长度字段
01类型(必须为 0x08 = 回显请求)
11代码(必须为 0x00)
2 - 32ICMP 校验和
4 - 52标识符
6 - 72序列号
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/)