好久没更新Blog了……放眼望去都快青青大草原了……

最近这段时间真的忙到起飞,也没时间打理自己的Blog,

现在闲下来了,总算有时间写点东西了……

正好之前也一直在研究BGP Peering技术,那这次就给大家带来一些BGP Peering相关的文章

(碎碎念部分结束)


在庞大的Internet中,存在着海量的路由器与主机。我们称这些路由器与主机为“节点”。

节点与节点之间的互联,需要路由协议的支撑。

如果是一个非常简单的网络,那我们用静态路由(Static Route)就足够让节点之间互联互通;

如果是一个稍微复杂些的中小型网络,此时使用静态路由就行不通了。

如果在简单网络中,用2~3条静态路由即可解决问题,

那么在中小型网络中,我们可能需要写数十甚至数百条路由,才能完成互联互通。

这时候,我们会考虑到RIP、OSPF等动态路由协议。

那么,问题来了:

在中小型的网络中,OSPF或许能够解决问题,

而当我们面对大型网络,甚至整个Internet时,我们就不能单纯使用RIP、OSPF这类的动态路由协议。

这个时候,我们就需要BGP动态路由协议;

但是,BGP在设计之初,就没有考虑到可能存在的劫持(Hijacking)问题,这也一定程度上,导致了曾经发生过的数次互联网瘫痪。

简单来讲,可以理解为有人把不属于自己的路由,发布到互联网上,让互联网上的节点都指向这些错误的路由,从而导致网络瘫痪;

稍微复杂点讲,因为某些网络管理员(Network Operator)的配置失误(甚至在部分情况下可能是恶意的),

某些不属于本网络的路由,甚至是默认路由,发布到了互联网,

进而导致所有的节点“错误”地使用了这些“错误”的路由,从而引发一场“灾难”。

那么,有没有什么办法,可以防止我们接收到这些错误的路由呢?

很快,聪明的人们提出了自己的想法:

“如果有人能够建立一个基础设施,用来对这些路由的有效性进行证明,不就可以解决这些问题了吗?”

那么,这个基础设施是什么?

它就是”RPKI (资源公钥基础设施)“。

Chapter 01: 介绍

首先,我们看下RPKI的定义:

资源公钥基础设施(Resource Public Key Infrastructure,简称RPKI),也称资源认证(Resource Certification),中文全称“互联网码号资源公钥基础设施”,是一项旨在使互联网路由基础设施更安全的公开密钥基础建设(PKI)框架。

正如其名,我们可以使用这些RPKI节点上的信息,用来证明我们收到的路由是“正确的”、“合法的”,

这样就可以杜绝我们的节点,接收到那些错误的路由,进而导致意外的发生。

这次,我们来构建一个本地的RPKI RTR节点,并使用Bird2作为RPKI客户端,对接收到的路由进行验证。

Chapter 02: 环境需求

如果想要搭建一个RPKI RTR节点,建议的最低配置为:

CPU: 1 核心
内存: 至少 1 GB 可用内存
网络: 稳定的网络连接

由于RPKI RTR节点需要将这些数据存储在内存中,所以内存理论上越大越好,但也不建议低于最低配置要求。

Chapter 03: 搭建RPKI RTR服务器

本次教程将使用Debian 10 x64作为系统环境,使用Bird 2.0.7作为路由软件,使用GoRTR v0.14.7作为RPKI RTR服务器软件。

本教程假定环境下并没有安装任何软件,一切从零开始(Build from Scratch),如果您已完成其中的部分步骤,请跳过。

03.01 安装 Bird2

由于目前存在于Debian 10镜像库中的Bird版本仅为Bird1 (Bird 1.6.6),建议大家尽快升级到Bird2版本,以获取更多功能。

我们从官方下载最新版本的Bird组件:

wget -O bird2.deb https://bird.network.cz/download/debian/pool/main/b/bird2/bird2_2.0.7-2+0~20191023.15+debian10~1.gbp23b01f_amd64.deb

由于此版本Bird2安装包依赖 libssh-gcrypt-4 软件包,所以我们无法直接使用 dpkg -i 方式安装此软件。

但毕竟天无绝人之路,我们还是有两种办法安装Bird2。

第一种方法,是手动安装缺少的软件包,然后再安装Bird:

apt install libssh-gcrypt-4 -y
dpkg -i bird2.deb
systemctl enable bird.service

第二种方法,是让apt自动补全缺少的依赖包:

apt install ./bird2.deb -y
systemctl enable bird.service

03.02 安装 GoRTR

完成上一步准备工作后,我们开始部署GoRTR:

此处可以选择两种安装方式:直接安装deb包,或者下载二进制文件后手动安装。

首先我们来看第一种:

我们开始下载GoRTR Deb包:

wget -O gortr.deb https://github.com/cloudflare/gortr/releases/download/v0.14.7/gortr_0.14.7_amd64.deb

之后安装:

dpkg -i gortr.deb
systemctl enable gortr.service

修改服务项的启动命令行 (此处为博主使用的配置,请根据实际情况进行修改):

vim /etc/default/gortr
GORTR_ARGS="-bind 127.0.0.1:8282 -verify.key /usr/share/gortr/cf.pub"
systemctl daemon-reload
service gortr restart

启动 GoRTR 后,请稍等一段时间(中国大陆境内服务器需要3-5分钟,海外服务器需要30秒左右),等待同步完成最新的RPKI数据。

第二种安装方法是:

直接下载二进制文件:

wget -O gortr https://github.com/cloudflare/gortr/releases/download/v0.14.7/gortr-v0.14.7-linux-x86_64
chmod +x gortr
wget -O cf.pub https://github.com/cloudflare/gortr/releases/download/v0.14.7/cf.pub

请将下载到的 cf.pub 放在一个自己喜欢的位置,用于GoRTR调用。

之后请根据自己实际情况,配置服务项/开机自启。启动命令行为:

gortr -bind 127.0.0.1:8282 -verify.key /usr/share/gortr/cf.pub

启动 GoRTR 后,请稍等一段时间(中国大陆境内服务器需要3-5分钟,海外服务器需要30秒左右),等待同步完成最新的RPKI数据。

03.03 配置 Bird2

当准备好GoRTR后,我们开始配置Bird2。

鉴于每个人的Bird2配置文件可能不同,以下内容仅放出确保正常运行用的关键代码,其他部分请使用自己的配置文件。

首先,我们在Bird2配置文件 /etc/bird/bird.conf 中,插入以下代码:

  • 定义 ROA 路由表
roa4 table roa4_internet;
roa6 table roa6_internet;
  • 定义 RPKI 协议
protocol rpki RPKI_Dual_Internet {
  roa4 {
    table roa4_internet;
  };
  roa6 {
    table roa6_internet;
  };
  remote "127.0.0.1" port 8282;
  retry keep 5;
  refresh keep 30;
  expire 600;
  transport tcp;
}
  • 定义 ROA 检查函数
function CheckRPKIROA_Internet() {
  if ( net.type = NET_IP4 && roa_check(roa4_internet, net, bgp_path.last) = ROA_INVALID ) then {
    return true;
  }
  else if ( net.type = NET_IP6 && roa_check(roa6_internet, net, bgp_path.last) = ROA_INVALID ) then {
    return true;
  }
  else {
    return false;
  }
}

这三者在配置文件中的代码顺序,建议为:

ROA 路由表
RPKI 协议
ROA 检查函数
BGP 协议

之后,我们可以在Bird2的BGP协议配置段,插入检测函数,用来检查入方向的BGP路由:

( ... )

import filter {
  if CheckRPKIROA_Internet() then reject;
  accept;
};

( ... )

修改完成后,建议使用 birdc configure 重载Bird2,而不建议使用 service bird restart 直接重启Bird进程。

重载Bird2的好处在于:

  • 如果你的Bird2配置文件有误,当重载遇到错误时,会停止重载流程,但Bird2进程还会继续运行(使用之前的正确配置维持原样);如果直接重启Bird2进程,因为配置文件错误,会导致Bird2报错无法拉起,进而导致Bird2停止工作;
  • 使用 birdc configure 重载Bird2,只会重载那些被修改过的协议,未被修改的协议将不会被影响(避免因使用重启导致的所有会话全部中断)

重载完成后,确认没有异常错误(返回类似这样的结果):

BIRD 2.0.7 ready.
Reading configuration from /etc/bird/bird.conf
Reconfigured

之后,使用命令,确认Bird2状态:

birdc show protocol
BIRD 2.0.7 ready.
Name       Proto      Table      State  Since         Info
( ... )
RPKI_Dual_Internet RPKI       ---        up     18:45:02.217  Established
( ... )
BGP_AS65001_MyNet BGP        ---        up     13:22:44.155  Established

使用命令,确认RPKI协议工作状态:

birdc show protocol all RPKI_Dual_Internet
BIRD 2.0.7 ready.
Name       Proto      Table      State  Since         Info
RPKI_Dual_Internet RPKI       ---        up     18:45:02.217  Established
  Cache server:     127.0.0.1:8282
  Status:           Established
  Transport:        Unprotected over TCP
  Protocol version: 1
  Session ID:       63709
  Serial number:    235
  Last update:      before 21.407 s
  Refresh timer   : 8.592/30
  Retry timer     : ---
  Expire timer    : 7178.592/7200
  Channel roa4
    State:          UP
    Table:          roa4_internet
    Preference:     100
    Input filter:   ACCEPT
    Output filter:  REJECT
    Routes:         185700 imported, 0 exported, 185700 preferred
    Route change stats:     received   rejected   filtered    ignored   accepted
      Import updates:         186473          0          0          0     186473
      Import withdraws:          773          0        ---          0        773
      Export updates:              0          0          0        ---          0
      Export withdraws:            0        ---        ---        ---          0
  Channel roa6
    State:          UP
    Table:          roa6_internet
    Preference:     100
    Input filter:   ACCEPT
    Output filter:  REJECT
    Routes:         31065 imported, 0 exported, 31065 preferred
    Route change stats:     received   rejected   filtered    ignored   accepted
      Import updates:          31277          0          0          0      31277
      Import withdraws:          212          0        ---          0        212
      Export updates:              0          0          0        ---          0
      Export withdraws:            0        ---        ---        ---          0

到此,配置大功告成。

如果你在 ROA 检查函数中,定义了输出到日志的行为,此时在日志中,就有可能发现那些被拦截掉的异常路由:

2021-02-13 17:15:08.358 <INFO> CheckRPKIROA_Internet(): RPKI/ROA Check Invalid - import 2001:db8::/48 (AS65502)
2021-02-13 17:15:08.363 <INFO> CheckRPKIROA_Internet(): RPKI/ROA Check Invalid - import ::/0 (AS65501)

通过使用 birdc show protocol all [协议名称],我们可以发现有被过滤(Filtered)掉的路由:

    Routes:         104298 imported, 3 exported, 104170 preferred
    Route change stats:     received   rejected   filtered    ignored   accepted
      Import updates:         201106          0        826          8     200272
      Import withdraws:        18192          0        ---        145      18047
      Export updates:         200368     200143        222        ---          3
      Export withdraws:        18047        ---        ---        ---          0
    BGP Next hop:   2001:db8:1234:abcd::2 fe80::bc49:50ff:fe16:4ab6

Chapter 04: 结语

正所谓:

路由千万条,
安全第一条,
过滤不规范,
邻居两行泪。

希望阅读本文章的读者,可以对BGP安全有简略认知,同时可以正确配置RPKI ROA验证以保护自己不受BGP路由劫持的伤害。

最后修改:2021 年 02 月 13 日
如果觉得我的文章对你有用,请随意赞赏