Skip to content

🌐 卷② 网络与 DNS

20 条。适用场景:连不上、偶发超时、解析结果不对

「要点」「我的补充」为本人撰写的背景与踩坑,非原文摘录;原文结论请点链接看原作者表述。

← 返回资料库总览


一、DNS:先把模型搞对,再谈排错

21. Why is DNS still hard to learn?

来源:Julia Evans · jvns.ca 读它解决什么:DNS 你学过好几次却总是记不牢——这条解释为什么它反直觉,而不是你笨。

要点

  • DNS 难学的一个核心原因是反馈回路极差:改一条记录,你看到的结果取决于一路上每层缓存的状态,试错很难收敛
  • 概念上还混着多套模型:权威服务器与递归解析器职责不同,而日常用的 dig/nslookup 默认问的是递归解析器
  • 术语本身也有历史包袱,很多名字(比如 zone、delegation)不看历史讲不通

我的补充:想拿到确定性结论,就绕开所有缓存直接问权威:dig @ns1.example.com example.com A +norecurse。改了 DNS 后别用本机 ping 验证——系统解析器(含 systemd-resolved / nscd)有自己的缓存,resolvectl flush-caches 才清得掉。工作中记住一句话:"我这边看到的是旧值"几乎永远是缓存,不是配置没生效。

阅读原文 →


22. Introducing "Implement DNS in a Weekend"

来源:Julia Evans · jvns.ca 读它解决什么:想真正理解 DNS 解析全过程——手写一个解析器是最快的路。

要点

  • 自己实现一遍会强制你面对报文格式:header、question、answer 各段的二进制布局
  • 会亲手走一次从根服务器开始的迭代查询:根 → TLD → 权威,这是平时被递归解析器隐藏掉的部分
  • 也会撞上 DNS 的实现细节,比如域名压缩指针——不处理就解析不出正确结果

我的补充:写完之后再看排障问题会通透很多。dig +trace 就是把这个迭代过程打印出来,理解了自己实现的版本,+trace 的每一行都能读懂。想验证委派是否正确,dig +trace 比问递归解析器可靠,因为它不吃中间缓存。

阅读原文 →


23. A toy DNS resolver

来源:Julia Evans · jvns.ca 读它解决什么:想看一个极简但完整的解析器长什么样,作为动手前的参照。

要点

  • 极短的实现足以完成"从根开始迭代直到拿到 A 记录"这条主干路径
  • 主干之外的复杂度大多来自健壮性:超时、重试、截断(TC 位)后回退 TCP、CNAME 链跟随
  • 读这种小实现的价值是看清"哪些是必须的,哪些是工程加固"

我的补充:TC 位那条在生产里真会遇到——响应超过 512 字节且未启用 EDNS0 时会被截断,客户端需改用 TCP 重查。这就是防火墙只放开 UDP 53、封了 TCP 53 时,大响应(多条记录、DNSSEC、TXT)会诡异失败而小查询正常的原因。排查 DNS 时永远记得测一次 dig +tcp

阅读原文 →


24. Making a DNS query in Ruby from scratch

来源:Julia Evans · jvns.ca 读它解决什么:想看不依赖任何 DNS 库、直接拼字节发查询是怎么做的。

要点

  • 手工构造报文能看清每个 flag 位的作用,尤其 RD(期望递归)位——它决定你是在请求递归还是只要权威回答
  • 域名不是明文写入的,而是按 label 长度前缀编码(3www7example3com0
  • 收到响应后要自己按段解析,这一步能暴露对报文结构的误解

我的补充:RD 位对应 dig+recurse/+norecurse。一个实用推论:向权威服务器发带 RD 的查询,它会忽略递归请求只答自己知道的部分,所以拿权威服务器当递归解析器用会得到不完整结果——有人配错 /etc/resolv.conf 指向权威 NS 就会遇到"部分域名解析不了"。

阅读原文 →


25. New tool: Mess with DNS!

来源:Julia Evans · jvns.ca 读它解决什么:想在不影响生产域名的前提下练手各种 DNS 记录配置。

要点

  • 提供可随意折腾的子域,改完立刻能查,把 DNS 那个糟糕的反馈回路缩短
  • 适合验证平时不常写的记录类型:SRV、CAA、TXT 的 SPF/DKIM 写法
  • 交互式练习对建立"改动 → 生效"的直觉比读文档有效

我的补充:强烈建议拿它先练两件真实工作中容易搞错的事:一是 CNAME 不能与其他记录共存(尤其不能在 zone apex 放 CNAME,这是很多人给根域配 CDN 时踩的坑,得用 ALIAS/ANAME 或 CNAME flattening);二是 SPF 记录只能有一条 TXT,多条会直接判为 permerror。

阅读原文 →


26. Migrating Mess With DNS to use PowerDNS

来源:Julia Evans · jvns.ca 读它解决什么:需要自建权威 DNS 时,了解一次真实迁移的取舍。

要点

  • 自己实现权威服务器与用成熟软件(PowerDNS/BIND/Knot)的分界点,通常在你开始需要 DNSSEC、AXFR、通知这些"周边"能力时
  • PowerDNS 的特点是后端可插拔(数据库存 zone),便于程序化管理记录
  • 迁移这类基础组件的关键是保证解析不中断,而不是新功能

我的补充:自建权威 DNS 有两条硬要求,漏了会很难查。一是至少两台 NS 且分布在不同网络/AS,注册商侧的 glue 记录要同步更新;二是 SOA 的 serial 必须在每次改 zone 后递增,否则从服务器不会拉取更新——用日期格式 YYYYMMDDNN 最省心。

阅读原文 →


27. Using less memory to look up IP addresses in Mess With DNS

来源:Julia Evans · jvns.ca 读它解决什么:需要在内存里做大规模 IP → 归属(ASN/地理)查询时的数据结构选择。

要点

  • IP 归属查询本质是"最长前缀匹配",用有序数组 + 二分或前缀树都能做,内存差别很大
  • 朴素做法(把每个 IP 展开成 map key)内存会爆掉,必须按网段存
  • 这类优化的常见收益来源是消除指针开销与提高内存局部性

我的补充:生产上别自己造——直接用 MaxMind 的 MMDB 格式(libmaxminddb),它就是为这件事设计的,内存映射后几乎不占常驻内存。这个博客站的 /api/geo 走 Cloudflare 边缘拿国家码,也是同一个思路:能让基础设施在边缘做的事,不要拉到自己进程里做

阅读原文 →


二、抓包与诊断命令

28. Examples for the tcpdump and dig man pages

来源:Julia Evans · jvns.ca 读它解决什么tcpdump 的 man page 你翻过十次仍然不知道该敲什么——这条给的是可直接用的例子。

要点

  • man page 缺的常常不是选项说明,而是完整可跑的示例
  • tcpdump 的门槛主要在 BPF 过滤表达式:hostportnetand/or/not 的组合方式
  • dig 的门槛在于输出分段(QUESTION/ANSWER/AUTHORITY)与常用开关(+short+trace@server

我的补充:三条我几乎每次都用的:tcpdump -i any -nn port 53-nn 不做名字/端口反解,否则抓 DNS 会自己触发 DNS 查询造成干扰)、tcpdump -i any -w /tmp/x.pcap 存盘后拖到 Wireshark 看、以及-c 1000 限量避免把磁盘写满。容器场景下 -i any 常常抓不到想要的流量,需要 nsenter 进目标网络命名空间。

阅读原文 →


29. Notes on clarifying man pages

来源:Julia Evans · jvns.ca 读它解决什么:理解为什么 man page 常常读不懂,从而知道该去哪里找答案。

要点

  • man page 的设计目标是完整的参考,不是教程,两者的信息组织方式天然冲突
  • 缺失最多的是"典型用法"和"这个选项什么时候真的需要"
  • 知道这一点后,正确策略是:man page 用来查准确语义,用法去找示例集合

我的补充:实用替代品:tldr(社区维护的示例集,npm i -g tldr 或包管理器装)、cheat,以及很多命令自带的 --help 比 man 更简洁。另外 man 7 <主题> 那一卷常被忽略但含金量高,比如 man 7 signalman 7 tcpman 7 capabilities 都是排查时的一手资料。

阅读原文 →


30. Monitoring tiny web services

来源:Julia Evans · jvns.ca 读它解决什么:只有几个小服务,上 Prometheus 全家桶太重——这条讨论最小可用监控。

要点

  • 小服务的监控目标很朴素:它挂了我要知道,其余都是加分项
  • 最小方案是外部黑盒探测(定期请求关键 URL,失败就告警),因为它检验的是用户实际路径
  • 自建监控的悖论是:监控系统和被监控服务同机时,一起挂就什么都收不到

我的补充:这个博客这类静态站,最划算的组合是:外部 uptime 探测(UptimeRobot / Better Stack 免费额度足够)+ Cloudflare 侧的错误率告警。探测点必须在你的基础设施之外。另外记得探测 URL 选一个真实渲染的页面而不是 /,CDN 常年 200 但源站已经坏掉的情况是存在的。

阅读原文 →


三、nginx 与 HTTP 服务

31. New tool: an nginx playground

来源:Julia Evans · jvns.ca 读它解决什么:nginx 配置改一版重载一次太慢,你需要一个能立刻看到匹配结果的沙箱。

要点

  • nginx 最容易出错的地方是 location 匹配优先级:精确 = > 前缀 ^~ > 正则(按出现顺序)> 普通前缀(最长者)
  • try_filesrootalias 的路径拼接规则不同,是 404 的高发区
  • 交互式验证比"改配置 → reload → curl"循环快一个量级

我的补充rootalias 的区别务必记牢:location /static/ { root /var/www; } 实际找 /var/www/static/...,而 alias /var/www;/var/www/...。另外改完配置nginx -treload-t 能挡掉大部分语法错;nginx -T 会打印合并所有 include 之后的完整配置,排查"到底哪条生效了"时非常有用。

阅读原文 →


32. Open sourcing the nginx playground

来源:Julia Evans · jvns.ca 读它解决什么:想知道这类"配置沙箱"怎么安全地跑用户提供的配置。

要点

  • 核心问题是隔离:执行不可信配置必须限制文件访问、网络与资源
  • 常见做法是容器或轻量沙箱(如 bubblewrap)加只读文件系统
  • 工具开源之后的价值是可自托管,用于内部配置评审

我的补充:这个思路可以搬到 CI 里——给 nginx/HAProxy 配置加一步语法与行为检查,比人工 review 靠得住。最低成本版本:CI 里跑 docker run --rm -v $PWD:/etc/nginx:ro nginx nginx -t,语法错直接卡住合并。再进一步可以起容器发几个 curl 断言关键 location 的返回码。

阅读原文 →


33. Hosting my static sites with nginx

来源:Julia Evans · jvns.ca 读它解决什么:自己用 nginx 托管静态站时,那份"最小但正确"的配置该长什么样。

要点

  • 静态站的关键项集中在几处:indextry_files 的回退顺序、404 页、gzip/brotli、缓存头
  • 多站点靠 server_name 区分,证书按站配置
  • 这类配置的失败模式通常不是崩溃,而是静默地行为不对(比如 404 返回了 200)

我的补充:多页静态站(像 VitePress 构建出来的)绝对不要配 SPA 式回退 try_files $uri /index.html;——所有真 404 会变成 200 首页,自定义 404 页永远不显示,还会被搜索引擎判为 soft 404。这个坑我在这个博客的 _redirects 里就遇到过。正确写法是 try_files $uri $uri/ $uri.html =404;,并单独配 error_page 404 /404.html;

阅读原文 →


34. Server-sent events: a simple way to stream events from a server

来源:Julia Evans · jvns.ca 读它解决什么:只需要服务器单向推送,不想为此引入 WebSocket。

要点

  • SSE 就是一个长连接的 HTTP 响应,Content-Type: text/event-stream,按 data: ...\n\n 分帧
  • 相比 WebSocket 的优势是走普通 HTTP、天然穿代理、浏览器端自动重连
  • 局限是单向(服务器 → 客户端)且有连接数限制

我的补充:反向代理后面用 SSE 必须关缓冲,否则消息会被攒住不发——nginx 里要 proxy_buffering off;proxy_read_timeout 调大,还要确保没有中间层做 gzip 缓冲。另外 HTTP/1.1 下浏览器对同域连接数有限制(约 6 个),开多个 SSE 标签页会互相饿死;HTTP/2 下没这个问题。

阅读原文 →


四、边缘网络与协议演进

35. BGP Role model: tracking the adoption of RFC 9234

来源:Cloudflare 博客 · blog.cloudflare.com 读它解决什么:了解 BGP 层面防止路由泄漏的机制进展。

要点

  • BGP 的历史问题是缺乏内建的关系约束:邻居之间是客户、供应商还是对等,协议本身不知道,全靠人工配策略
  • RFC 9234 引入在会话建立时声明角色,让设备能自动拒绝违反关系的路由通告
  • 这类机制的价值取决于采纳率,单方部署收益有限

我的补充:对不运营 AS 的人来说,实际意义是理解"路由泄漏"为什么能让你的服务在某些地区突然不可达而你的机器毫无异常。遇到"部分地区访问不了"先别查服务器:用 RIPE Atlas 或不同地区的 traceroute 看路径,再对比 Cloudflare Radar / BGPStream 有没有相关事件。这类问题你改不了,只能确认并等上游修。

阅读原文 →


36. Cloudflare DDoS Threat Report H1 2026

来源:Cloudflare 博客 · blog.cloudflare.com 读它解决什么:了解当前 DDoS 的规模量级与主流手法,用来判断自己的防护是否够。

要点

  • 报告类资料的用法不是记数字,而是看趋势与攻击类型分布:容量型(L3/L4 洪泛)与应用层(HTTP 请求洪泛)的防护手段完全不同
  • DNS 洪泛被单独点出,说明权威/递归 DNS 是常被忽视的攻击面
  • 攻击峰值持续上升,意味着"自建清洗"对个人和中小团队基本不现实

我的补充:个人站的现实结论很简单——把 DNS 和 HTTP 都放在有清洗能力的服务商后面,并且别暴露源站 IP。源站 IP 泄漏的常见途径是历史 DNS 记录、邮件头、证书透明日志里的旧记录,以及直接绑 IP 的子域。这个博客是 Cloudflare Pages + Functions,源站这个概念本身就不存在,是最省心的形态。

阅读原文 →


37. Total eclipse of the Internet: traffic impacts in Iceland, Spain, and Portugal

来源:Cloudflare 博客 · blog.cloudflare.com 读它解决什么:理解流量异常并不总意味着故障——外部事件会显著改变流量形状。

要点

  • 大规模真实事件(日食、赛事、停电)会让区域流量出现明显偏移,这类数据来自网络侧的宏观观测
  • 对运维的含义是:基线是有前提的,节假日、事件期间的同比环比对比会失真
  • 排障时先问"是不是只有我这样",能省掉大量无效工作

我的补充:落到实践就是告警阈值不要只用静态值。流量骤降先查是不是区域性事件或某个大客户自身在维护,再查自己。Cloudflare Radar 可以免费看区域流量趋势,是判断"是不是只有我"的便宜手段。同理,流量突增也别急着扩容——先确认不是爬虫或攻击。

阅读原文 →


38. Certificate Transparency Monitoring is now generally available

来源:Cloudflare 博客 · blog.cloudflare.com 读它解决什么:想知道有没有人给你的域名签发了你不知道的证书。

要点

  • CT(证书透明)要求 CA 把签发记录写入公开可审计的日志,任何人都能查
  • 监控 CT 日志能发现未授权签发,这是域名劫持/中间人的早期信号
  • 反过来,CT 也意味着你的所有子域名都是公开信息

我的补充:后半句常被忽略,但很关键:给内部系统签公网证书,等于把子域名结构公开admin.example.comjenkins.example.com 这类名字会直接出现在 CT 日志里,crt.sh 上一搜就有,攻击者的资产测绘第一步就是这个。内部系统要么用内部 CA,要么用通配符证书。免费监控可以直接用 crt.sh 的 RSS/邮件订阅。

阅读原文 →


39. A revisit of remote Spectre attacks on Cloudflare Workers

来源:Cloudflare 博客 · blog.cloudflare.com 读它解决什么:理解多租户边缘运行时如何应对侧信道攻击,以及这对你的部署意味着什么。

要点

  • Spectre 类攻击利用推测执行的时序差异跨越隔离边界读取本不该读的数据
  • 多租户平台的缓解手段通常是组合式的:限制高精度计时、隔离调度、进程/isolate 边界加固
  • 这类风险无法靠应用代码消除,取决于平台

我的补充:对使用者的实际含义有两条。一是边缘函数里不要放长期有效的高价值密钥,用短期令牌或平台托管的 secret 绑定。二是自己写的代码里别提供"精确计时 + 任意内存读"的组合能力——比如把用户输入直接当索引访问大数组还回报耗时,这等于自己造了个侧信道。这个博客的 Functions 只做壁纸列表和地理国家码,故意不碰任何敏感数据,就是这个思路。

阅读原文 →


40. How Cloudflare detects MCP traffic and helps secure it

来源:Cloudflare 博客 · blog.cloudflare.com 读它解决什么:AI agent 开始访问你的服务后,需要识别并管控这类流量。

要点

  • MCP(Model Context Protocol)流量的行为模式与浏览器和传统爬虫都不同,识别方式也要跟着变
  • 管控点通常在边缘:识别、限速、要求认证,而不是等打到应用层
  • 传统的"UA 黑名单 + IP 封禁"对这类流量效果有限

我的补充:现在给自己站点做防护,除了传统爬虫还要考虑 AI agent 抓取。robots.txt声明不是强制,真要限制得靠边缘规则(Cloudflare 的 Bot 管理或自定义 WAF 规则)。反过来说,如果你希望内容被 AI 检索到,就别一刀切封掉——先想清楚要的是哪种结果。查现状可以在 Cloudflare 分析里按 UA 看 AI 爬虫占比。

阅读原文 →


本卷小结

三条最值钱的:

  1. DNS 问题九成是缓存。要确定性结论就 dig @权威 +norecurse,别用 ping 验证解析。
  2. 多页静态站别配 SPA 回退try_files $uri /index.html 会把真 404 变成 200,SEO 上是净损失。
  3. CT 日志是公开的。给内部系统签公网证书等于公开你的子域名结构,资产测绘第一步就查这个。

← 上一卷:性能诊断与 eBPF · 返回总览 · 下一卷:Kubernetes 与容器 →