能够让互联网(以及我们所熟知的生活)崩溃的三个协议:DNS、PKI 和 BGP

本文深入探讨了互联网核心协议DNS、PKI和BGP的固有脆弱性及其潜在威胁。作者指出这些协议的安全缺陷可能导致大规模网络中断或被恶意控制,并提出了如DNSSEC等解决方案。文章强调了互联网的脆弱性,呼吁加强其韧性以应对未来挑战。

你可能没有注意到,但瑞士已经建立了BGP (Border Gateway Protocol)的安全替代方案 [ here]:

为什么?BGP提供了互联网的核心,但它是一个路由协议,其内置的安全性非常低,可能被国家用来控制互联网。它也很容易被错误配置,导致互联网大面积中断。

韧性

随着希思罗机场最近关闭了一天,许多人都在谈论我们关键国家基础设施的韧性,其中最重要的部分之一就是互联网。虽然过去我们使用专线来增加通信基础设施的韧性,但现在,我们都使用互联网来提供可靠且经济的通信方式。没有它,世界上任何地方的飞机都无法起飞,我们的现代生活将比COVID-19时期遭受更大的停滞。事实上,如果不是互联网,COVID-19对世界的影响会更大。所以,想象一下如果整个互联网瞬间关闭会怎样!

互联网最初被设想为一个完全分布式、相互连接的机器网络,能够抵御攻击,但它距离这个目标还很遥远。基本上,它是用1980年代创建的“旧”协议构建的,那时大型机和小型计算机主宰着计算世界。IP (RFC 791)、TCP (RFC 792)、HTTP、DNS等协议自它们在RFCs (Request for Comments)中的最初草案以来几乎没有改变。事实上,HTTP一直在努力超越1.0版本。

因此,网络安全专业人士知道有三个根本性的弱点可能瞬间导致整个基础设施崩溃。它们是DNS (Domain Naming System)、PKI (Public Key Infrastructure)和BGP (Border Gateway Protocol)。

DNS

因此,我们的互联网协议存在需要修复的缺陷。但是,“仅仅足够”的安全性对于提供互联网核心服务:DNS (Domain Name Service)来说,是否足够呢?最大的威胁之一是DNS缓存投毒,恶意主机可以在网络中植入不正确的域名。DNSSEC通过设置一个受保护的区域来克服这个问题,该区域中的所有响应都经过数字签名。DNS解析器随后可以检查DNS信息是否由其中一个受信任的主机签名。

DNS如何使互联网瘫痪

对核心DNS基础设施进行大规模分布式拒绝服务 (DDoS) 攻击会使大部分互联网瘫痪,因为我们非常依赖DNS服务器来解析IP地址。如果核心停止工作,其余的基础设施将崩溃。并且,任何时候,我们的DNS基础设施都可能被恶意目的接管。

DNS是一个糟糕的协议。它依赖于一个DNS服务器告诉其他服务器域名解析的IP地址。但是你能信任谁来播种这个信息呢?嗯,域名的主要权威机构。我们不必集成主要权威机构,因为域名的信息将通过互联网传播。那么,如果一个恶意实体播种了错误的IP地址会发生什么?假设一个国家——MegaTropolis——想要接管一个小国家——MiniTropolis。那么,他们的首要任务可能是向世界各地的DNS缓存投毒,以便所有MiniTopolis的域名都指向MegaTropolis的网站。

域名系统安全扩展 (DNSSEC)

DNS的问题在于它几乎没有内置真正的安全性,并且可以很容易地设置一个虚假的DNS系统并将用户重定向到错误的网站。但有一个解决方案……域名系统安全扩展 ( DNSSEC)。它提供了DNS数据的源认证以及数据完整性。它不会阻止有人查看请求和回复中的数据。与DNS相关的问题已为人所知一段时间 [ here]:

威胁包括:数据包拦截;ID猜测和查询预测;名称链式攻击;受信任服务器的背叛;拒绝服务;域名认证拒绝;以及通配符。最大的威胁之一是DNS缓存投毒,恶意主机可以在网络中植入不正确的域名。DNSSEC通过设置一个受保护的区域来克服这个问题,该区域中的所有响应都经过数字签名。DNS解析器随后可以检查DNS信息是否由其中一个受信任的主机签名。

DNS通过创建定义SOA (Start of Authority) 的域记录来工作。这随后定义了序列号、刷新时间等:

在此之内,我们可以定义NS (Name Server) 和MX (Mail Server),以及域内已定义主机的IP地址。我们可以使用nslookup来查询条目:

应该注意的是,DNSSEC不提供数据的机密性,也不防范拒绝服务攻击。

编码示例

一些Go语言的编码在 [ here]。通过它,我们将创建一个2,048位的RSA密钥对(一个公钥和一个私钥),然后使用受信任域的私钥对SOA进行签名。其他人可以使用受信任域的公钥来检查签名。SOA条目是按照DNS中那样创建的,带有一个用于域名和IP地址的响应头 (dns.ClassINET):

序列号在SOA中很重要,因为它定义了条目的最新版本。在这种情况下,签名是使用RSA加密的SHA-256哈希创建的。我们还包括了签名的过期日期。签名由密钥中定义的实体 (key.Hdr.Name) 签名 [ here]:

package main
import (
    "crypto"
    "crypto/rsa"
    "github.com/miekg/dns"
    "fmt"
    "os"
)
func main() {
    domain:="asecuritysite.com"
    argCount := len(os.Args[1:])
        if (argCount>0) {domain= string(os.Args[1])}
    domain = domain+"."
    key := new(dns.DNSKEY)
    key.Hdr.Name = domain
    key.Hdr.Rrtype = dns.TypeDNSKEY
    key.Hdr.Class = dns.ClassINET
    key.Hdr.Ttl = 3600
    key.Flags = 256
    key.Protocol = 3
    key.Algorithm = dns.RSASHA256
    priv, _ := key.Generate(2048)
    soa := new(dns.SOA)
    soa.Hdr = dns.RR_Header{domain, dns.TypeSOA,dns.ClassINET, 14400, 0}
    soa.Ns = "ns."+domain
    soa.Mbox = "mail."+domain
    soa.Serial = 1293945905
    soa.Refresh = 14400
    soa.Retry = 3600
    soa.Expire = 604800
    soa.Minttl = 86400
    sig := new(dns.RRSIG)
    sig.Hdr = dns.RR_Header{domain, dns.TypeRRSIG, dns.ClassINET, 14400, 0}
    sig.TypeCovered = dns.TypeSOA
    sig.Algorithm = dns.RSASHA256
    sig.Labels = 2
    sig.Expiration = 1562761057
    sig.Inception = 1562761057
    sig.OrigTtl = soa.Hdr.Ttl
    sig.KeyTag = key.KeyTag()
    sig.SignerName = key.Hdr.Name
    var pr crypto.Signer
    pr,_= newSignerFromKey(priv)
    if err := sig.Sign(pr, []dns.RR{soa}); err != nil {
        fmt.Printf("Failed to sign")
        return
    }
    if err := sig.Verify(key, []dns.RR{soa}); err != nil {
        fmt.Printf("Failed to verify")
    } else {
        fmt.Printf("Signature okay\n\n")
    }
    fmt.Printf("SOA: %s\n\n",soa)
    fmt.Printf("Sig: %s\n\n",sig)
    fmt.Printf("Key: %s\n\n",key)

}
type rsaPrivateKey struct {
    *rsa.PrivateKey
}
func newSignerFromKey(k interface{}) (crypto.Signer, error) {
    var sshKey crypto.Signer
    switch t := k.(type) {
    case *rsa.PrivateKey:
        sshKey = &rsaPrivateKey{t}
    default:
        return nil, fmt.Errorf("ssh: unsupported key type %T", k)
    }
    return sshKey, nil
}

对于“asecuritysite.com.”消息的示例运行在 [ here]:

Signature okay

SOA: asecuritysite.com. 14400   IN  SOA ns.asecuritysite.com. mail.asecuritysite.com. 1293945905 14400 3600 604800 86400
Sig: asecuritysite.com. 14400   IN  RRSIG   SOA 8 2 14400 20190710121737 20190710121737 42450 asecuritysite.com. NqFhFsl
EHFtETdO1cWFKhMyWydiTDpGkWKQggzgbzVGa9COBQDrFS+NRsVEQEpIee3EMJ/hY6RXpmo75ZxWO7OO4FfIBbl2qgZctewmutFy+HT4GUFA3dJp9rzfr2Jn
0lnCCOkLIW33zHgXgSXmKJobWXPsHTPQoUogjdxmPzbzWFd6S1XXPep4klyi1hbcM9uvnABtFGw5tb/rd7hs6B/hS9spoO5MHZqDczmAKEoW1XKht12G97Qc
Qz3nyyGlRScntbHNXk3xaD3Xzevu9SWhZ4Ro2xFvIWxdFkLWCv2wZkcwHIG9q7zFE5HglZhip+q8EKzfZV1PQn8AOVf16dA==
Key: asecuritysite.com. 3600    IN  DNSKEY  256 3 8 AwEAAdcn7cvHVXBvDQVsh6ge+JHZWTCn4WarBbWzQ1TGKMpk/pT9L386Q2ZU1fvynYdp
eqQi4PKbRpavycjqMFBtJvg9qhHpXq25iSpdx1+aNHL8zyvx/eFFTAWHA8qN3uQuVKc5mm+KQ498poWd1dnYBNHRcNGgZA8epNsq+WSoLzRISIxgiFDs6j+k
ryO4ivj7n8dLOqqcv9C/tQl/7YhU4y3lHSek9FqFOCpYK4DzQb+jJuLKNWjAPobWF19JkrvcN0KeDZ2TZEeApz3UGtjsRMowH4AJ48yKyaT2vnmE52MwIiC1
/yHLtQJK77CMgow3BejXO2T9uytp+rTQyZk8Ens=

PKI (Public Key Infrastructure)

好像DNS还不够糟糕一样,对PKI进行一次小小的调整就能使几乎所有系统崩溃。通过PKI,我们用实体的公钥来识别它,并且它将通过用其关联的私钥对某些数据的哈希进行签名来证明其身份。但是我们必须确保我们信任我们收到的公钥,因此我们将公钥封装在数字证书中,然后用受信任机构的私钥对其进行签名。如果我们信任该机构,那么我们就会信任数字证书中的公钥。

为此,我们有根CA (Certificate Authorities) 和中间CA。根CA有权限允许中间CA为特定领域的证书签名,例如TLS连接、硬件设备和加密磁盘。这些机构的公钥存储在计算机上,用于检查证书的有效性。在这种情况下,Bob让小Trent为他的公钥签名,然后Bob将带有他公钥的签名证书传递给Alice。Alice随后用小Trent的公钥检查,如果验证通过,她就可以信任Bob的公钥。然后Bob可以对他的身份进行数字签名:

总的来说,根CA在这里是根本性必需的,因为如果小Trent不受Trent的信任,小Trent的证书将无效。因此,如果根CA的私钥遭到大规模黑客攻击,或者对手发送了针对根CA的撤销请求,互联网的整个“纸牌屋”都可能倒塌。世界各地的机器将不再信任任何证书,并且由于无法信任服务而无法连接。

目前,谷歌正在考虑用Merkle Root方法取代PKI,在这种方法中,实体的公钥可以包含在Merkle Tree中,实体只需证明从Merkle Root到其公钥的路径即可。

BGP (Border Gateway Protocol)

现在,别让我开始谈论BGP这场灾难。它有着导致整个域名长时间瘫痪的悠久记录,例如让Facebook下线一整天。但是,我们很幸运,它没有让整个域名离线一天,它可能会让整个互联网长时间离线。没有交通,没有能源供应,没有食品供应等等。

所以互联网并不是DARPA试图创建的大规模分布式网络,也不是能够抵御核打击的网络。它的核心是路由设备的中心化基础设施和中心化的互联网服务。这些协议本身基本上就是我们从哑终端连接到大型计算机时起草的那些。总的来说,其核心基础设施的一个小故障就可能导致整个系统彻底崩溃。而且,如果你无法连接到网络,你通常会很难修复它。有点像当你把自己锁在车外又没有钥匙时,试图修车一样。

由于BGP仍然提供了互联网核心的重要部分,它出现的任何问题都可能导致大规模中断。最近,Facebook因为BGP配置错误而从互联网上消失,并且多次发生互联网流量被“欺骗”通过那些隐私记录不佳的国家。

BGP是互联网路由的核心,通过定义自治系统 (AS) 来工作。AS通过ASN (Autonomous System Number) 标识,并维护路由表,允许AS之间传递数据包,从而在它们之间进行路由。因此,Facebook的AS可以向其他ASs宣告它的存在,并且数据包可以路由到它们。当Facebook发生中断时,Facebook的AS未能宣告其存在。然后,每个AS定义它可以到达的网络范围。Facebook的ASN是AS32935,覆盖大约270,000个IP地址范围 [ here]。

什么是BGP?

近代历史上的两种主要域间路由协议是EGP (Exterior Gateway Protocol) 和BGP(Border Gateway Protocol)。EGP存在一些限制,其主要限制是它将互联网视为树状结构,如图1所示。这假定互联网的结构由父子关系组成,并带有一个单一主干。互联网更典型的拓扑结构如图2所示。BGP现在是应用最广泛的外部路由协议之一,并已在很大程度上取代了EGP。

图1:单一主干——树状拓扑

图2:多主干

BGP是EGP的改进版本(BGP的第四个版本称为BGP-4),定义在RFC1772中。不幸的是,它比EGP更复杂,但不如OSPF复杂。BGP假定互联网由任意互连的节点组成。然后它假定互联网连接到许多AANs(自主连接网络),如图3所示,这些网络在组织、互联网服务提供商等周围创建边界。然后它假定一旦数据包进入AAN,就会被正确路由。

图3:自主连接网络

大多数路由算法都试图找到通过网络的最快路径,而BGP则试图找到通过网络的任何路径。因此,主要目标是可达性,而不是到达目的地的跳数。所以,找到一条接近最优的路径就是一个很好的成就。AAN管理员选择至少一个节点作为BGP speaker,以及一个或多个边界网关。这些网关只是将数据包路由进出AAN。边界网关是数据包到达AAN所经过的路由器。

AAN上的speaker向其AAN内的所有网络广播其可达性信息。此信息仅说明是否可以到达目标AAN;它不描述任何其他度量。重要的一点是,BGP不是距离矢量或链路状态协议,因为它传输的是完整的路由信息而不是部分信息。

BGP更新数据包还包含无法到达的路由信息(撤销路由),BGP-4更新数据包的内容是:

  • 不可达路由长度(2字节)。
  • 撤销路由(可变长度)。
  • 总路径属性长度(2字节)。
  • 路径属性(可变长度)。
  • 网络层可达性信息(可变长度)。这可以包含额外信息,例如“优先使用AAN 1而不是AAN 2”。

AS内的路由器共享相似的路由策略,因此作为单个管理单元运行。AS之外的所有路由器都将AS视为一个单一单元。AS识别号由互联网号码分配机构 (IANA) 分配,范围为1到65,535,其中64,512到65,535保留用于私人使用。私有号码仅在私有域内使用,当离开该域时必须转换为注册号码。

BGP和路由循环

BGP使用TCP段在端口179上发送路由信息(而RIP使用端口520)。BGP通过构建自治系统图来克服路由循环,该图基于邻居之间交换的信息。因此,它可以构建整个互连AS的更广阔视图。邻居之间会发送keep-alive消息,这使得该图能够保持最新。

单宿主系统

只有一个出口点的AS被定义为单宿主系统,通常被称为stub network。这些stub network可以使用默认路由来处理所有目的地为非本地网络的流量。

AS可以通过三种方法使外界了解AS内的地址:

  • 静态配置。为此,互联网接入提供商可以在其自己的路由器中将客户网络列为静态条目。然后这些条目将被广播到连接到其互联网核心的其他路由器。这种方法也可以与CIDR方法一起使用,该方法聚合路由。
  • 在链路上使用内部网关协议 (IGP)。为此,互联网接入提供商可以在单一连接上运行IGP,这可以用于广播连接的网络。此方法比静态配置提供更动态的方法。典型的IGP是OSPF。
  • 在链路上使用外部网关协议 (EGP)。EGP可用于广播网络。如果连接的AS没有注册的AS号,互联网接入提供商可以从私有AS号池(64,512到65,535)中分配一个,然后在向互联网核心广播AS时将其剥离。

多宿主系统

多宿主系统从AS有多个出口点。由于它有多个出口点,它可以支持数据在这些出口点之间的路由。不支持流量通过AS路由的系统称为非中转AS。因此,非中转AS只会向互联网接入提供商广播自己的路由,因为它不希望任何流量通过它们路由。如果某个互联网提供商知道可以通过AS路由,它可能会强制流量通过该AS。为了克服这个问题,AS会设置过滤以阻止任何此类路由流量。

多宿主中转系统与互联网接入提供商有多个连接,并允许流量通过它路由。它将通过在内部运行BGP来路由此流量,以便同一AS中的多个边界路由器可以共享BGP信息。同时,路由器可以将BGP信息从一个边界路由器转发到另一个。在AS内部运行的BGP被称为内部BGP (IBGP),而在AS外部运行的BGP被称为外部BGP (EBGP)。定义AS和互联网接入提供商之间边界的路由器被称为边界路由器,而运行内部BGP的路由器被称为中转路由器。

BGP规范

边界网关协议 ( BGP) 是一种自治系统间路由协议(外部路由协议),它建立在EGP之上。基于BGP的系统的主要功能是与其他BGP系统通信网络可达性信息。最初,两个系统交换消息以打开和确认连接参数,然后传输整个BGP路由表。之后,随着路由表的更改,会发送增量更新。

每条消息都有一个固定大小的头部,并且可能后面跟着一个数据部分。字段如下:

  • 标记。 包含消息接收方可以预测的值。它可用于检测一对BGP peers之间的同步丢失,以及验证传入的BGP消息。16字节。
  • 长度。 指示消息的总长度(以字节为单位),包括头部。它必须始终大于18且不大于4096。2字节。
  • 类型。 指示消息的类型,例如1 — OPEN、2 — UPDATE、3 — NOTIFICATION和4 — KEEPALIVE。

OPEN消息

OPEN消息是建立连接后发送的第一条消息。随后会发送一条KEEPALIVE消息确认OPEN消息。此后,可以交换UPDATE、KEEPALIVE和NOTIFICATION消息。

图4显示了添加到固定大小BGP头部中的额外信息。它包含以下字段:

  • 版本。 指示消息的协议版本号。典型值为2、3或4。1字节。
  • 我的自治系统。 标识发送方的自治系统号。2字节。
  • 保持时间。 指示接收连续KEEPALIVE和/或UPDATE和/或NOTIFICATION消息之间可能经过的最大秒数。2字节。
  • 认证码。 指示正在使用的认证机制。这应定义认证数据的形式和含义以及计算标记字段值的算法。
  • 认证数据。 此字段的形式和含义是可变长度字段,取决于认证码。

图4:BGP消息头部和BGP OPEN消息数据

BGP配置

BGP配置命令类似于用于RIP (Routing Internet Protocol) 的命令。要配置路由器以支持BGP,请使用以下命令:

RouterA # config t
RouterA(config)# router bgp AS-number

对于IGP(例如RIP),network 命令定义了发送路由表更新的网络。对于BGP,使用不同的方法来定义网络之间的关系。这在 [ here]:

RouterA # config t
RouterA(config) # router bgp AS-number
Router(config-router)# network network-number [mask network-mask]

其中network 命令定义了向何处广播本地学习到的网络。这些网络可能已经从其他协议(如RIP)中学到。network 命令可以使用可选的mask 来指定单个子网。对于BGP协议,邻居必须建立关系;为此,使用以下命令:

RouterA # config t
RouterA(config) #router bgp AS-number
Router(config-router)#network network-number [mask network-mask]
Router(config-router)# neighbor ip-address remote-as AS-number

这定义了连接的基于BGP的路由器的IP地址及其AS号。

结论

从核心来看,互联网并不是一个去中心化的基础设施。它脆弱,容易受到人为错误和对抗性攻击。我们花费太多时间让服务工作,而很少关注如何使其健壮。我们需要投入更多时间来研究各种场景以及如何缓解它们。以前,是Facebook让自己下线;下一次,可能是一个国家让整个国家瘫痪……这很可能会产生毁灭性的影响。

  • 原文链接: billatnapier.medium.com/...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
billatnapier
billatnapier
江湖只有他的大名,没有他的介绍。