github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/docs/translations/zh_CN/linux/external_fuzzing_network.md (about)

     1  > [!WARNING]
     2  >
     3  > **请注意,这是社区驱动的官方 syzkaller 文档翻译。当前文档的最新版本(英文版)可在 [docs/linux/external_fuzzing_network.md](/docs/linux/external_fuzzing_network.md) 找到。**
     4  
     5  Linux 内核的外部网络模糊测试
     6  =========================================
     7  
     8  syzkaller 已支持对网络栈的外部模糊测试。
     9  这是通过使用 [TUN/TAP](https://www.kernel.org/doc/Documentation/networking/tuntap.txt) 接口来实现的.
    10  它允许设置一个虚拟网络接口,并将从外部网络接收到的数据包发送到内核。
    11  这触发了真实数据包通过真实网络接口传递的相同路径(除了驱动层)。
    12  
    13  您需要启用 `CONFIG_TUN` 内核配置来开启外部网络模糊测试。
    14  关于如何设置虚拟接口,请参考 [executor/common_linux.h](/executor/common_linux.h) 中的 `initialize_tun()` 函数。
    15  
    16  相关模板描述可在 [sys/linux/vnet.txt](/sys/linux/vnet.txt) 中找到。
    17  目前有两个系统调用: `syz_emit_ethernet` 和 `syz_extract_tcp_res`。
    18  第一个伪系统调用通过虚拟接口向外发送数据包。
    19  第二个伪系统调用尝试从外部接收数据包,并从中解析 TCP 序列号,以便在后续的数据包中使用。
    20  目前还有很多协议或协议扩展尚未描述,因此非常欢迎补充!
    21  
    22  由于模糊测试可能在同一个虚拟机实例内的多个执行器进程中进行,我们需要一种方式来隔离不同执行器的虚拟网络。
    23  目前,这是通过为每个执行器创建一个虚拟接口,并为这些接口分配不同的 MAC 地址、IPv4 地址和 IPv6 地址来实现。
    24  然后,模板描述利用 `proc` 类型来为每个执行器生成适当的地址。
    25  
    26  由于许多网络协议需要将校验和字段嵌入到数据包中,因此支持描述此类字段。
    27  这里存在一个 `csum` 类型,目前支持两种不同类型的校验和计算:
    28  Internet 校验和 [the Internet checksum](https://tools.ietf.org/html/rfc1071) : `csum[parent, inet, int16be]`,
    29  以及类似于 TCP 的伪头部校验和: `csum[tcp_packet, pseudo, IPPROTO_TCP, int16be]`。
    30  在通过虚拟接口发送数据包之前,这些校验和会被计算并嵌入其中。
    31  这里还有一个很好的特性:当 syzkaller 生成 C 语言 reproducer 时,它也会生成代码并在运行时重新计算校验和。
    32  
    33  通过使用 `syz_emit_ethernet` and `syz_extract_tcp_res`,以下 syzkaller 程序能够建立基于 IPv4 的 TCP 连接:
    34  
    35  ```
    36  mmap(&(0x7f0000000000/0x10000)=nil, (0x10000), 0x3, 0x32, 0xffffffffffffffff, 0x0)
    37  r0 = socket$inet_tcp(0x2, 0x1, 0x0)
    38  bind$inet(r0, &(0x7f0000001000)={0x2, 0x0, @empty=0x0, [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]}, 0x10)
    39  listen(r0, 0x5)
    40  syz_emit_ethernet(0x36, &(0x7f0000002000)={@local={[0xaa, 0xaa, 0xaa, 0xaa, 0xaa], 0x0}, @random="4c6112cc15d8", [], {{0x800, @ipv4={{0x5, 0x4, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x6, 0x0, @remote={0xac, 0x14, 0x0, 0xbb}, @local={0xac, 0x14, 0x0, 0xaa}, {[]}}, @tcp={{0x1, 0x0, 0x42424242, 0x42424242, 0x0, 0x0, 0x5, 0x2, 0x0, 0x0, 0x0, {[]}}, {""}}}}}})
    41  syz_extract_tcp_res(&(0x7f0000003000)={<r1=>0x42424242, <r2=>0x42424242}, 0x1, 0x0)
    42  syz_emit_ethernet(0x38, &(0x7f0000004000)={@local={[0xaa, 0xaa, 0xaa, 0xaa, 0xaa], 0x0}, @remote={[0xbb, 0xbb, 0xbb, 0xbb, 0xbb], 0x0}, [], {{0x800, @ipv4={{0x5, 0x4, 0x0, 0x0, 0x2a, 0x0, 0x0, 0x0, 0x6, 0x0, @remote={0xac, 0x14, 0x0, 0xbb}, @local={0xac, 0x14, 0x0, 0xaa}, {[]}}, @tcp={{0x1, 0x0, r2, r1, 0x0, 0x0, 0x5, 0x10, 0x0, 0x0, 0x0, {[]}}, {"0c10"}}}}}})
    43  r3 = accept$inet(r0, &(0x7f0000005000)={0x0, 0x0, @multicast1=0x0, [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]}, &(0x7f0000006000)=0x10)
    44  ```
    45  
    46  ```
    47  Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
    48  tcp        0      0 0.0.0.0:20000           0.0.0.0:*               LISTEN      5477/a.out
    49  tcp        2      0 172.20.0.170:20000      172.20.0.187:20001      ESTABLISHED 5477/a.out
    50  ```
    51  
    52  对于 IPV6 来说也有类似的程序:
    53  
    54  ```
    55  mmap(&(0x7f0000000000/0x10000)=nil, (0x10000), 0x3, 0x32, 0xffffffffffffffff, 0x0)
    56  r0 = socket$inet6_tcp(0xa, 0x1, 0x0)
    57  bind$inet6(r0, &(0x7f0000000000)={0xa, 0x1, 0x0, @empty={[0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]}, 0x0}, 0x1c)
    58  listen(r0, 0x5)
    59  syz_emit_ethernet(0x4a, &(0x7f0000001000)={@local={[0xaa, 0xaa, 0xaa, 0xaa, 0xaa], 0x0}, @random="de895db1468d", [], {{0x86dd, @ipv6={0x0, 0x6, "a228af", 0x14, 0x6, 0x0, @remote={0xfe, 0x80, [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], 0x0, 0xbb}, @local={0xfe, 0x80, [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], 0x0, 0xaa}, {[], @tcp={{0x0, 0x1, 0x42424242, 0x42424242, 0x0, 0x0, 0x5, 0x2, 0x0, 0x0, 0x0, {[]}}, {""}}}}}}})
    60  syz_extract_tcp_res(&(0x7f0000002000)={<r1=>0x42424242, <r2=>0x42424242}, 0x1, 0x0)
    61  syz_emit_ethernet(0x4a, &(0x7f0000003000)={@local={[0xaa, 0xaa, 0xaa, 0xaa, 0xaa], 0x0}, @random="de895db1468d", [], {{0x86dd, @ipv6={0x0, 0x6, "a228af", 0x14, 0x6, 0x0, @remote={0xfe, 0x80, [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], 0x0, 0xbb}, @local={0xfe, 0x80, [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], 0x0, 0xaa}, {[], @tcp={{0x0, 0x1, r2, r1, 0x0, 0x0, 0x5, 0x10, 0x0, 0x0, 0x0, {[]}}, {""}}}}}}})
    62  r3 = accept$inet6(r0, &(0x7f0000004000)={0x0, 0x0, 0x0, @empty={[0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]}, 0x0}, &(0x7f0000005000)=0x1c)
    63  ```
    64  
    65  ```
    66  Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
    67  tcp6       0      0 :::20001                :::*                    LISTEN      5527/a.out
    68  tcp6       0      0 fe80::aa:20001          fe80::bb:20000          ESTABLISHED 5527/a.out
    69  ```