[翻译] 深入了解 Verizon 和 BGP 优化工具是如何导致大部分互联网离线的

笔记本约 5.7 千字

一周以前,由于一起 BGP 路由泄漏事故导致 Cloudflare 出现了大规模的离线事故。Cloudflare 随后在其博客上发布了一篇关于事故的简报和一篇关于路由泄漏的分析。本文即是对第二篇路由泄漏分析的翻译。

原文标题:The deep-dive into how Verizon and a BGP Optimizer Knocked Large Parts of the Internet Offline Monday
原文作者:Martin J Levy
原文链接:https://blog.cloudflare.com/the-deep-dive-into-how-verizon-and-a-bgp-optimizer-knocked-large-parts-of-the-internet-offline-monday/
原文刊载于 The Cloudflare Blog,本文由 Sukka 翻译,首发于 Sukka's Blog

让我们回顾一下周一发生了什么

星期一,我们写了一篇关于大规模 BGP 路由泄漏的文章。我们在文章中写道,这次事故本来不会发生,因为 Verizon 不应该将这部分路由转发到互联网。文章在 UTC 时间晚上 19 时 58 分,也就是 BGP 路由泄漏之后七个小时(大家将会看到,路由泄漏事件结束的具体时间是 UTC 时间 12:39)发布的。今天,我们将通过对存档的路有数据进行深入研究和分析。我们在文中将会使用大部分读者都能够理解的简单的 Shell 命令,读者们也可以自己对路由表进行调查。

这是一起广为人所知的 BGP 路由泄漏事件,大部分在线新闻媒体都进行了报道。Andree Toonk 在推特上发布了 2400 个受到影响的 ASN 的列表。

在这篇文章中包含了大量的首字母缩略词,这些缩写会在文章的最后进行解释。

RIPE NCC 的归档数据

RIPE NCC 运营着一个非常有用的 BGP 路由存档,收集全球的 BGP 路由并提供一个公开的 API 用来查询数据。你可以在 https://stat.ripe.net 上找到更多相关信息。在 BGP 的世界中,所有路由都是公开的(任何人都能在其能力范围内收集足够的数据)。存档数据对于研究(比如我们在文章中做的事情)非常有价值。这个网站可以将一些非常有用的数据做成可视化的图表。

cf-bgp-leak/1.png

从 RIPEstat 获取这次事件的相关数据

目前,RIPEstat 的数据不能实时获取,一般需要等待 8 到 12 小时。RIPEstat 的数据可以通过 Web 界面或者 API 获取。我们通过请求 API 获取到了 JSON 格式的数据。

虽然有很多其它的 ASN 受到本次 BGP 路由泄漏事件的影响,但是我们将只关注关于 Cloudflare 的泄漏路由。我们只处理有限的数据,并聚焦在 Cloudflare 的路由发生了什么。以下所有指令可以在很多系统上运行,我们使用了运行在 MacBook Pro 上的 macOS Mojave。相关脚本和原始数据已经上传到 GitHub。

首先,我们收集了过去 24 小时 来自 AS13335(Cloudflare)的路由宣告和 AS-PATH。

$ # 获取 24 小时范围内的数据——大大超过我们需要的
$ ASN="AS13335"
$ START="2019-06-24T00:00:00"
$ END="2019-06-25T00:00:00"
$ ARGS="resource=${ASN}&starttime=${START}&endtime=${END}"
$ URL="https://stat.ripe.net/data/bgp-updates/data.json?${ARGS}"
$ # 从 RIPEstat 获取数据
$ curl -sS "${URL}" | jq . > 13335-routes.json
$ ls -l 13335-routes.json
-rw-r--r--  1 martin  staff  339363899 Jun 25 08:47 13335-routes.json

这将下载 340MB 的数据——看起来很多,但是它包含大量空白和大量我们不需要的数据。接下来我们的任务就是从这些原始数据中找到我们所需要的数据——时间戳、实际路由和 AS-PATH,其中 AS-PATH 数据非常有用。注意我们使用了 jq,macOS 可以通过 brew 软件包管理器进行安装。

$ # 提取时间戳、时间路由和 AS-PATH
$ jq -rc '.data.updates[]|.timestamp,.attrs.target_prefix,.attrs.path' < 13335-routes.json | paste - - - > 13335-listing-a.txt
$ wc -l 13335-listing-a.txt
691318 13335-listing-a.txt

现在我们减少到了不到 70 万次路由事件,但是这些并不是 BGP 路由泄漏,而是包括 Cloudflare 的 AS13335 的所有数据。为此,我们回到周一的文章(译者注:即文章开头提到的文章)并且知道 AS396531(Allegheny Technologies)和 AS701(Verizon)出现在了 BGP 路由泄漏中。现在我们可以进一步减少数据:

$ # 提取路径为 701,396531 的数据
$ # AS701 - Verizon,AS396531 - Allegheny Technologies
$ egrep '701,396531' < 13335-listing-a.txt > 13335-listing-b.txt
$ wc -l 13335-listing-b.txt
204568 13335-listing-b.txt

现在数据看起来少多了,我们只需要面对 20.4 万个数据点。然而这依然是一个规模很大的数据,因为路由拓扑在发生变化时 BGP 可能会变得非常冗长。这正是 BGP 路由泄漏事件将会导致的情况。现在让我们看看有多少路由收到了影响。

$ # 提取被泄漏事件影响的路由
$ cut -f2 < 13335-listing-b.txt | sort -V -u > 13335-listing-c.txt
$ wc -l 13335-listing-c.txt
101 13335-listing-c.txt

现在数字小多了,我们列出了至少 101 条通过 Verizon 泄漏的路由。这份列表可能并不完整,因为 RIPEstat 这样的路由收集器并不能从 Verizon 直接获得数据,因此这些数据包含的是 Verizon 的路径和其它路径,查看上述文件中列出的 AS-PATH 时能够注意到这一点。

译者注:在这篇文章首次发布时,译者发现这篇文章中的脚本使用的参数存在错误,-n 这个参数将只能够获取有限的数据,获取全部数据应该使用 -V 参数。相关资料 可以在 StackOverflow 上查看。文章的作者后来意识到了这个错误并进行了修改。

这是一份受到影响的路由的不完整列表。

$ cat 13335-listing-c.txt
8.39.214.0/24
8.42.245.0/24
8.44.58.0/24
...
104.16.80.0/21
104.17.168.0/21
104.18.32.0/21
104.19.168.0/21
104.20.64.0/21
104.22.8.0/21
104.23.128.0/21
104.24.112.0/21
104.25.144.0/21
104.26.0.0/21
104.27.160.0/21
104.28.16.0/21
104.31.0.0/21
141.101.120.0/23
162.159.224.0/21
172.68.60.0/22
172.69.116.0/22
...

这份列表非常有趣,因为其中一些路由的发起者被标注为 AS13335,但是这些路由并非属于 Cloudflare 的网络。比如我们从未宣告过 104.26.0.0/21,但是我们宣告了 104.26.0.0/20。更重要的是,我们拥有 IRR 和这个 IP 段的 RPKI ROA。

这是 IRR 的数据:

route:          104.26.0.0/20
origin:         AS13335
source:         ARIN

这是 RPKI ROA 的数据。我们将 ROA 的最大长度设置为 20、因此不应该接受比较小的路径。

Prefix:       104.26.0.0/20
Max Length:   /20
ASN:          13335
Trust Anchor: ARIN
Validity:     Thu, 02 Aug 2018 04:00:00 GMT - Sat, 31 Jul 2027 04:00:00 GMT
Emitted:      Thu, 02 Aug 2018 21:45:37 GMT
Name:         535ad55d-dd30-40f9-8434-c17fc413aa99
Key:          4a75b5de16143adbeaa987d6d91e0519106d086e
Parent Key:   a6e7a6b44019cf4e388766d940677599d0c492dc
Path:         rsync://rpki.arin.net/repository/arin-rpki-ta/5e4a23ea-...

ROA 中的最大长度表示可接受的宣告的大小。事实上,这是一条最大长度为 /20/20 的路由,意味着包含在这个段中的 /21 (或者 /22 /23 /24)是不被允许的。进一步查看上述列表中的路由,可以得到如下的列表:

Route Seen            Cloudflare IRR & ROA    ROA Max Length
104.16.80.0/21    ->  104.16.80.0/20          /20
104.17.168.0/21   ->  104.17.160.0/20         /20
104.18.32.0/21    ->  104.18.32.0/20          /20
104.19.168.0/21   ->  104.19.160.0/20         /20
104.20.64.0/21    ->  104.20.64.0/20          /20
104.22.8.0/21     ->  104.22.0.0/20           /20
104.23.128.0/21   ->  104.23.128.0/20         /20
104.24.112.0/21   ->  104.24.112.0/20         /20
104.25.144.0/21   ->  104.25.144.0/20         /20
104.26.0.0/21     ->  104.26.0.0/20           /20
104.27.160.0/21   ->  104.27.160.0/20         /20
104.28.16.0/21    ->  104.28.16.0/20          /20
104.31.0.0/21     ->  104.31.0.0/20           /20

所以为什么 /21 会出现呢?这就是我们深入研究 BGP 路由优化工具、以及他们会倾向于合成不应该存在的路由的现象。如果这些路由发生了泄漏(是的,这一星期就发生了一起),那么世界末日就来了。尤其是现在有两个 ISP(而不是只有一个)允许这些无效路由在它们的自治网络之外自由传播。我们将在这篇文章之中继续探索这些 AS-PATH。

20 年以前,RFC1997 为 BGP 添加了 community 这个概念。community 是一种标记和分组路由广播的方式。community 通常用于标记路由,以便可以应用特定处理策略。RFC1997 包含了少数通用的、知名的 community,其中有一个 NO_EXPORTS community 包括了以下规范:

All routes received carrying a communities attribute
containing this value MUST NOT be advertised outside a BGP
confederation boundary (a stand-alone autonomous system that
is not part of a confederation should be considered a
confederation itself)

译者注:上述规定的翻译如下:所有收到包含此值的 community 属性的路由 禁止 在 BGP 联盟之外广播。不属于联盟的 AS 应当被视为联盟本身。
BGP 联盟是一种使用 BGP 将单个 AS 细分为多个内部子 AS 的方法,但在宣告时仍使用单个 AS。

在 BGP 网络中,NO_EXPORTS community 是非常常见的,这有助于缓解 BGP 路由泄漏、
BGP 路由优化工具的工作原理(以及它们为什么会捅娄子)足够再写一篇文章了。

路由泄漏事件发生的时间

我们在所有的文件中都保留了时间戳,因此我们可以通过数据中第一列和最后一列的时间戳来确认每一条路由泄漏的时间。我们保存了 UTC 0 时 0 分 0 秒到次日 0 时 0 分 0 秒的数据,这已经副高了路由泄漏事件发生的时间段。我们编写了一个脚本,以时间对这些路由事件进行排序。

$ # 获取路由泄漏事件的时间
$ while read cidr
do
  echo $cidr
  fgrep $cidr < 13335-listing-b.txt | head -1 | cut -f1
  fgrep $cidr < 13335-listing-b.txt | tail -1 | cut -f1
done < 13335-listing-c.txt |\
paste - - - | sort -k2,3 | column -t | sed -e 's/2019-06-24T//g'
...
104.25.144.0/21   10:34:25  12:38:54
104.22.8.0/21     10:34:27  12:29:39
104.20.64.0/21    10:34:27  12:30:00
104.23.128.0/21   10:34:27  12:30:34
141.101.120.0/23  10:34:27  12:30:39
162.159.224.0/21  10:34:27  12:30:39
104.18.32.0/21    10:34:29  12:30:34
104.24.112.0/21   10:34:29  12:30:34
104.27.160.0/21   10:34:29  12:30:34
104.28.16.0/21    10:34:29  12:30:34
104.31.0.0/21     10:34:29  12:30:34
8.39.214.0/24     10:34:31  12:19:24
104.26.0.0/21     10:34:36  12:29:53
172.68.60.0/22    10:34:38  12:19:24
172.69.116.0/22   10:34:38  12:19:24
8.44.58.0/24      10:34:38  12:19:24
8.42.245.0/24     11:52:49  11:53:19
104.17.168.0/21   12:00:13  12:29:34
104.16.80.0/21    12:00:13  12:30:00
104.19.168.0/21   12:09:39  12:29:34
...

可以看到,路由泄漏事件是在 2019 年 6 月 24 日 UTC 10:34:25 开始、并在 UTC 时间 12:38:54 结束,持续了两个多小时。这是一张图表,展示了每条泄漏的路由持续的时间。

cf-bgp-leak/2.png

我们可以回到 RIPEstat 查看 AS13335 的活动图表:

cf-bgp-leak/3.png

显然,在 UTC 时间 10 时 30 分到 12 时 40 分之间发生了很多路由活动——远远超过正常水平。

值得注意的是,我们提到过 RIPEstat 并不能获取完整的 Verizon 的路由,因此这张图并没有包含全部传播的路由。

深入分析 AS-PATH

拥有这些路由数据很有用,但是现在我们要查看这些被泄漏的路由的路径以知晓哪些 ASN 受到了影响。现在我们将会深入挖掘这些归档的数据,查看路由泄漏的程度和范围。

$ # 提取路由泄漏事件中的 AS-PATH
$ # 通过路由列表获取完整的 AS-PATH
$ # 合并路径
$ # 幸运的是,我们知道 AS-PATH 中最后几个 ASN 是一致的
$ cut -f3 < 13335-listing-b.txt | tr -d '[\[\]]' |\
awk '{
  n=split($0, a, ",");
  printf "%50s\n",
    a[n-5] "_" a[n-4] "_" a[n-3] "_" a[n-2] "_" a[n-1] "_" a[n];
}' | sort -u
   174_701_396531_33154_3356_13335
   2497_701_396531_33154_174_13335
   577_701_396531_33154_3356_13335
   6939_701_396531_33154_174_13335
  1239_701_396531_33154_3356_13335
  1273_701_396531_33154_3356_13335
  1280_701_396531_33154_3356_13335
  2497_701_396531_33154_3356_13335
  2516_701_396531_33154_3356_13335
  3320_701_396531_33154_3356_13335
  3491_701_396531_33154_3356_13335
  4134_701_396531_33154_3356_13335
  4637_701_396531_33154_3356_13335
  6453_701_396531_33154_3356_13335
  6461_701_396531_33154_3356_13335
  6762_701_396531_33154_3356_13335
  6830_701_396531_33154_3356_13335
  6939_701_396531_33154_3356_13335
  7738_701_396531_33154_3356_13335
 12956_701_396531_33154_3356_13335
 17639_701_396531_33154_3356_13335
 23148_701_396531_33154_3356_13335

这个脚本清晰地列出了泄漏的路由的 AS-PATH,并且他们有一致的特点。从后往前看,我们可以看到 13335(Cloudflare),3356 和 174(Level3、CenturyLink 或 Cogent,Cloudflare 的 Tier 1 Transit)。然后是 33154(DQE Communications)和 396531(Allegheny Technologies Inc)。目前为止,技术上来讲这并不算泄漏(虽然趋近于泄漏),因为我们不知道这两个 AS 之间的关系。他们之间可能有 Mutual Transit 协议,这取决于它们。

回到 AS-PATH 继续向左看,我们看到了非常糟糕、非常明显的路由泄漏的证据。首先,这与 Transit 中泄漏了从客户到非客户之间时的路由完全一致——Verizon 并没有将 13335 列为客户。其次,这些路由包含了 Tier 1 的 ASN。本来 ISP 应该通过过滤来压制路由泄漏,但是这就是潜在的威胁。

译者注:原文中使用了 dragons there be 这个短语,根据维基百科对 Here be dragons 的解释,是指中世纪在航海地图上使用龙等危险动物来标记地图上未知区域(这部分区域可能存在未被发现的暗礁)的行为。译者在此翻译成潜在的威胁。

是的,那里的确存在威胁!你现在可以看到 Verizon 是如何过滤(准确说,如何不过滤)他的客户的。跟在 701 左边的是和 Verizon 对等互联、或者接受了 Verizon 泄漏的路由的客户,大部分都是 Tier 1 ISP:174(Cogent)、1239(Sprint)、1273(Vodafone)、3491(PCCW)、6461(Zayo)等。

本来上述列表中应该还包括三个值得一提的网络——1299(Telia)、2914(NTT)(译者注:NTT IS THE BEST!)和 7018(AT&T)。这三个网络实现了一个非常简单的 AS-PATH 过滤器,因此在那一天他们成功保护了自己的网络。他们仅仅只是禁止 Tier 1 ISP 向他们发送下一层中包含 Tier 1 ISP 的路由。因为如果这条路由意味着每一个 Tier1 ISP 完全连接到其它的 Tier 1 ISP 上,这正是路由泄漏的表现之一。互联网的全局 BGP 路由表的拓扑结构简单地指出,包含多个 Tier 1 ISP 的路应该被过滤掉。

除此以外,我们还知道 7018(AT&T)会丢弃包含非法的 RPKI 的路由,而 Cloudflare 的路由是使用 RPKI 签名的,因此 AT&T 从 Verizon 接收到这些路由时会直接丢弃。是的,这是 RPKI 的完全胜利!

请记住,我们一直在讨论 Cloudflare 没有宣告的路由。这些路由都是某些路由优化工具的。

Verizon 应该从他们的客户 AS396531 接收哪些路由?

这是个好问题,通常情况下我们应该查看 IRR 以查看 ASN 的路由的策略。

$ whois -h whois.radb.net AS396531 ; the Verizon customer
%  No entries found for the selected source(s).
$ whois -h whois.radb.net AS33154  ; the downstream of that customer
%  No entries found for the selected source(s).

是的,这足以说明我们不应该在互联网上任何地方看到这两个 ASN。但是,我们应该找到更多的证据。既然我们知道这两个 ASN 了,我们可以搜索这些 ASN 列出的所有的路由。然后我们找到了:

$ whois -h whois.radb.net ' -i origin AS396531' | egrep '^route|^origin|^mnt-by|^source'
route:          192.92.159.0/24
origin:         AS396531
mnt-by:         MNT-DCNSL
source:         ARIN

现在,我们找到了持有箱管 IRR 的人。我们可以看看这个网络还有什么东西(正是我们正在寻找的):

$ whois -h whois.radb.net ' -i mnt-by -T as-set MNT-DCNSL' | egrep '^as-set|^members|^mnt-by|^source'
as-set:         AS-DQECUST
members:        AS4130, AS5050, AS11199, AS11360, AS12017, AS14088, AS14162,
                AS14740, AS15327, AS16821, AS18891, AS19749, AS20326,
                AS21764, AS26059, AS26257, AS26461, AS27223, AS30168,
                AS32634, AS33039, AS33154, AS33345, AS33358, AS33504,
                AS33726, AS40549, AS40794, AS54552, AS54559, AS54822,
                AS393456, AS395440, AS396531, AS15204, AS54119, AS62984,
                AS13659, AS54934, AS18572, AS397284
mnt-by:         MNT-DCNSL
source:         ARIN

这列出了这个网络预计向互联网宣告的下游 ASN,很显然不论是 Cloudflare 还是其它受到影响的 ASN 都没有列在其中。

我们可以对 Verizon 的 ASN 进行相同的实践。我们只寻找 33154 以避免列出太多路由。

$ whois -h whois.radb.net ' -i origin AS33154' | egrep '^mnt-by' | sort -u
mnt-by:         MNT-DCNSL
mnt-by:     MAINT-AS3257
mnt-by:     MAINT-AS5050

这些都与 33154 不直接相关,这是其它方创建的。我们的搜索遇到了死胡同。

于是这值得进行进一步搜索查看是否有包含 33154 和 396531 的任何 as-set,我们转向了由 NLNOG 运营的 IRR Explorer。我们使用 http://irrexplorer.nlnog.net/search/33154 搜索到了如下 as-set:

cf-bgp-leak/4.png

有趣的是我们看到这个 ASN 被列入了其它 as-set,但是没有一个和周一的路由泄漏有关。接下来让我们看看 396531。

cf-bgp-leak/5.png

这表明我们不需要再检查别的地方了。AS-DQECUST 是控制(应该说它们有义务控制)其网络的过滤。

所有调查都基于一个可靠的基础:Verizon 的客户的 IRR 中并没有列出 Cloudflare。考虑到有 2300 多个 ASN 受到了路由泄漏影响,我们可以推断出 Verizon 没有任何过滤、路由泄漏并没有被缓解。

IPv6 的路由泄漏在哪里?

我们可以确认的是,星期一没有任何关于 IPv6 的路由泄漏。

为什么?因为事实证明,396531 并没有启用 IPv6。通常情况下,Cloudflare 会嘲笑任何没有启用 IPv6 的网络,但是在这次事件中,我们很高兴 IPv6 在路由泄漏事件中幸存下来。

那么这是不是可以将星期一发生的事称为 IPv4 路由泄漏?事实并非如此。来让我们看看 Cloudflare 向 Verizon 发送的 IPv6 流量的百分比(和 IPv4 相比)。通常情况下,这个比例是稳定的。

cf-bgp-leak/6.png

这种 IPv6 流量的上升可能是 Happy Eyeballs 在移动手机上选择使用 IPv6 而不是 IPv4 前往 Cloudflare 的直接结果。Happy Eyeballs 旨在防止 IPv6 失败,但是在这种特定情况下,它在防止 IPv4 故障上一样做得非常出色。但是我们必须小心这个图表,因为经过进一步思考和调查以后,由于 IPv4 的减少,百分比是上升的有的时候图表可能会出错,但是虽终端用户受到了影响,Happy Eyeballs 还是干得很好。

译者注:Happy Eyeballs,也被称作 Fast Fallbacks,是在 RFC6555RFC8305 定义的双栈快速回退机制。通过同时对 IPv4 和 IPv6 进行连接,IPv6 在当前网络中不可用时仍然能继续使用 IPv4 进行连接。通常情况下,Happy Eyeballs 的实现都会优先使用 IPv6。

使用带宽图确认路由泄漏和网络稳定性

正如我们说过的,Verizon 已经影响了他们自己的用户。让我们以他们的带宽图开始:

cf-bgp-leak/7.png

红线是 2019 年 6 月 24 日的,灰色线条是前几天的、用于对比。这张图也包括 Verizon 的宽带和移动数据业务。

AT&T 带宽图就完全不一样了:

cf-bgp-leak/8.png

这直接确认了 AT&T 在这次路由泄漏事件中 完全没有受到影响。

再来看一个 Tier 1 的网络。6762(意大利电信)受到了这次路由泄漏的影响,因为 Cloudflare 和意大利电信有直接互联。

cf-bgp-leak/9.png

有了这份数据,我们就可以要求意大利电信改善他们的路由过滤机制。

本可能在周一时提供帮助的一些未来的工作

IETF 小组正在 BGP 路由保护领域和 SIDROPS 小组(安全域间路由操作工作组)合作,他们的章程是:

The SIDR Operations Working Group (sidrops) develops guidelines for the operation of SIDR-aware networks, and provides operational guidance on how to deploy and operate SIDR technologies in existing and new networks.

SIDR 小组为 SIDR 感知网络的运营制定指南,并提供有关如何在现有网络和新的网络中部署与运行 SIDR 技术的指南。

这个小组最新的成果,Alexander Azimov 等人的名为 draft-ietf-sidrops-aspa-profile 草案应该被广为告知,以展示像星期一的路由泄漏事件的严重性。这份草案扩展了 RPKI 的数据结构,Cloudflare 和其它一些公司对这份草案的进一步发展很感兴趣。但无论如何,Cloudflare 都会反复重申:Cloudflare 鼓励所有 ISP 和 NOC 立刻部署 RPKI 技术

专有名词介绍

  • API - 应用程序接口
  • AS-PATH - 目前为止已经遍历的 ASN 列表
  • ASN - 为互联网上的每个网络分配的唯一编号
  • BGP - 边界网关协议,互联网的核心路由协议
  • IETF - 互联网工程任务组,一个开放的标准组织
  • IRR - 互联网路由注册表,记录路由的数据库
  • ISP - 互联网接入服务提供商
  • RFC - 征求意见稿,由 IETF 发布,被视为规范
  • RIPE NCC - 欧洲网路资讯中心,一个区域互联网注册机构
  • ROA - BGP 路由宣告时使用的加密签名
  • RPKI - 用于路由信息的公钥基础设施框架
  • Sukka - 这篇文章的译者
  • Tier 1 - 没有默认路由、并且和其它所有 Tier 1 对等互联的网络
  • UTC - 世界协调时,一种时间标准
[翻译] 深入了解 Verizon 和 BGP 优化工具是如何导致大部分互联网离线的
本文作者
Sukka
发布于
2019-07-03
许可协议
转载或引用本文时请遵守许可协议,注明出处、不得用于商业用途!
如果你喜欢我的文章,或者我的文章有帮到你,可以考虑一下打赏作者
评论加载中...