为什么对一个关闭的 UDP 端口狂发,只能收到零星几个“端口不可达”?traceroute 里的星号一定是路径有问题吗?这篇直接测量本机和网关回 ICMP 差错的速度,对比 echo 应答、TCP RST 和被禁用的时间戳 / 掩码请求。
net.inet.icmp.maskrepl: 0 net.inet.icmp.timestamp: 0 net.inet.icmp.drop_redirect: 1 net.inet.icmp.log_redirect: 0 net.inet.icmp.bmcastecho: 1 net.inet.icmp.suppress_icmp_port_unreach: 0 net.inet.icmp.fraglimit: 16 net.inet.icmp.fragtimeout: 5 net.inet.ip.redirect: 1 net.inet.ip.forwarding: 0 net.inet.icmp 下没有 icmplim 这一项:macOS 不像 Linux / BSD 那样用 sysctl 设 ICMP 限速;下面一节直接测量 netstat -s -p icmp 的 Input histogram 里没有“redirect”一项;Output histogram 里的类别:echo reply,destination unreachable
net.inet.icmp 下有 maskrepl、timestamp、drop_redirect、bmcastecho 等开关,但没有 ICMP 限速的 sysctl。
间隔 0 ms:3 秒内发了 374840 个 UDP 包,抓到 31 个 ICMP 差错(10.3 个/秒);相邻差错的间隔 最小 99 / 中位 100 / 最大 100 ms;netstat 里 icmp_error 调用 +31,“destination unreachable”输出 +31 间隔 1 ms:3 秒内发了 2961 个 UDP 包,抓到 30 个 ICMP 差错(10.0 个/秒);相邻差错的间隔 最小 99 / 中位 100 / 最大 100 ms;netstat 里 icmp_error 调用 +30,“destination unreachable”输出 +30 间隔 5 ms:3 秒内发了 598 个 UDP 包,抓到 30 个 ICMP 差错(10.0 个/秒);相邻差错的间隔 最小 100 / 中位 100 / 最大 101 ms;netstat 里 icmp_error 调用 +30,“destination unreachable”输出 +30 间隔 10 ms:3 秒内发了 300 个 UDP 包,抓到 30 个 ICMP 差错(10.0 个/秒);相邻差错的间隔 最小 100 / 中位 100 / 最大 101 ms;netstat 里 icmp_error 调用 +30,“destination unreachable”输出 +30 间隔 50 ms:3 秒内发了 60 个 UDP 包,抓到 30 个 ICMP 差错(10.0 个/秒);相邻差错的间隔 最小 100 / 中位 100 / 最大 100 ms;netstat 里 icmp_error 调用 +30,“destination unreachable”输出 +30 间隔 200 ms:3 秒内发了 15 个 UDP 包,抓到 15 个 ICMP 差错(5.0 个/秒);相邻差错的间隔 最小 200 / 中位 200 / 最大 200 ms;netstat 里 icmp_error 调用 +15,“destination unreachable”输出 +15 间隔 1000 ms:5 秒内发了 5 个 UDP 包,抓到 5 个 ICMP 差错(1.0 个/秒);相邻差错的间隔 最小 1000 / 中位 1000 / 最大 1000 ms;netstat 里 icmp_error 调用 +5,“destination unreachable”输出 +5 结论:不管发多快,最多约每 100 ms 回一个差错(≈ 10 个/秒);发得慢于这个速度时每个都回
本机生成 ICMP 差错的速度上限约为每 100 ms 一个,发包再快也不增加;发得慢于这个速度时每个都回。限掉的包没有走到生成 ICMP 的步骤,netstat 的计数也不增加。
ICMP echo:发出 3000 个请求(抓到 3000 个请求),收到 3000 个应答——echo 应答没有被限成 10 个/秒 TCP:对没人监听的端口连续发起 1500 次 connect(0.07 秒),抓到 1500 个 SYN,回了 1500 个 RST——TCP 的拒绝(RST)在这里没有被限成 10 个/秒 UDP 端口不可达(ICMP):3 秒内发了 374840 个,只回了 31 个
限速针对 ICMP 差错报文(这里测的是端口不可达);echo 应答和 TCP 的 RST 没有被限制。
端口不可达(发到网关自己的关闭端口):103 ms 内发了 100 个,收到 4 个差错;相邻间隔 最小 0 / 中位 0 / 最大 2 ms 超时(TTL=1,网关要转发时发现 TTL 用完):103 ms 内发了 100 个,收到 3 个差错;相邻间隔 最小 2 / 中位 2 / 最大 2 ms 设备各有各的策略(有的按速率、有的按令牌桶);这里只看到这台网关回应的个数,没有看到它的配置
默认网关对端口不可达和超时也只回几个,回应集中在最初几毫秒。traceroute 里的星号和只回 1/3 的跳,有一部分只是路由器在限速。
对 127.0.0.1 发 时间戳请求(类型 13):1 秒内从套接字收到 1 个 ICMP 包,类型 [13]——应答类型是 14,没有收到 对 127.0.0.1 发 地址掩码请求(类型 17):1 秒内从套接字收到 1 个 ICMP 包,类型 [17]——应答类型是 18,没有收到 对 127.0.0.1 发 回显请求(类型 8,对照):1 秒内从套接字收到 1 个 ICMP 包,类型 [0]——应答类型是 0,收到了
timestamp = 0、maskrepl = 0 时,本机不回时间戳请求和地址掩码请求;redirect 方面本机丢弃收到的重定向(drop_redirect = 1)且不转发(ip.forwarding = 0)。