はじめに
最近、RPKIが気になっている。とあるISPのインターンでRPKIの話題が出たのがきっかけだ。そのときは軽い説明程度で、「へ〜、ほうほう」とおもっただけなのだが、BGP関連の話で頻繁に登場するため、これはきちんと理解しておくべき技術なのではないかと感じた。
そこで本記事では、CML ( Cisco Modeling Labs ) を用いたミニチュアRPKI環境の構築と動作確認を通じて、RPKIの理解を深めることを目的とする。具体的には、NLnet Labsが提供するKrill(子CA)とRoutinator(RPKI Validator)を構築し、実際にROAを発行して、BGPルータ上で「経路の正当性がどのように判定されるのか」を確認する。
最終的に、「ROAを発行するとBGPの経路選択にどのような変化が起きるのか」を目で見て確認するところまでを目標とする。
背景 - 経路ハイジャック
経路ハイジャック ( BGPハイジャック ) は、インターネットの通信経路を偽装して、他人のネットワーク宛てのデータを横取りしたり遮断したりするものです。
実際にどのように経路ハイジャックが起きるのかを、以下の構成図で簡単に説明します。
構成としては、AS1、AS2、AS3、AS4の4つのASがある状態で、各ASは隣接ASとピアを張っている状態です。そして、AS3は「10.0.0.0/16」というアドレス範囲を保有しており、AS2やAS1に対して「このネットワークは自分のものです」とBGPを使って経路情報を広報しています。インターネットではBGPの情報をもとにルータが最適な経路を判断するため、AS1から10.0.0.0/16宛ての通信はAS2を経由してAS3へ届きます。
しかし、悪意を持ったAS4が「10.0.0.0/16は自分のネットワークだ」と嘘の経路情報を広報します。すると、AS1はAS4とも直接接続しているため、AS4からの情報を受け取ります。BGPはASパスが短い/またはパス属性によりAS4経由が優先される場合があります。これにより、AS4は通信を盗み見たり、改ざんしたり、最悪の場合はすべて破棄することも可能となります。
ここで登場するのが RPKI ( Resource Public Key Infrastructure ) です。
AS3が「10.0.0.0/16はAS3が正当な発信元である」という内容の ROAを発行していれば、AS1やAS2は経路情報を受け取る際にRPKIデータベースを参照し、「この経路の発信元ASは正しいか?」を検証します。
AS4の虚偽経路はこの検証で失敗し、「無効 ( invalid ) 」と判定されるため、AS1はAS4からの経路を採用しません。
結果として、AS1は正当なAS3の経路のみを維持し、不正な経路ハイジャックを防ぐことができます。
RPKI ( Resource Public Key Infrastructure ) とは
ここでは、前述で登場した RPKIについて、もう少し詳しく説明します。
RPKIは、IPアドレスやAS番号といったインターネット上のリソースに対して「誰が正当な所有者であるかを証明」し、その情報をもとに BGP の経路広報が正しいかどうかを検証できる仕組みです。
大まかな流れとしては、
-
組織が自分のプレフィックスに対してROAを作成
-
CAがそのROAを受け取り、リポジトリに登録
-
各ネットワークのROAキャッシュサーバがROAを同期・検証
-
検証済みROA ( VRP ) をキャッシュサーバに保持
-
BGPルータがキャッシュを参照して経路の正当性を判定
といった流れになります。
以降では、各用語について触れていきます。
CA ( Certificate Authority:認証局 )
RPKI の基盤を支えているのが CA です。
各地域インターネットレジストリ ( RIR:APNIC、ARIN、RIPE NCCなど ) は、自身が割り当てたリソースに対して リソース証明書 ( Resource Certificate ) を発行します。
組織 ( LIRやISP ) はその証明書を使って、「自分が正当に管理しているプレフィックスである」ことを第三者に証明できます。
たとえば:
- RIPE NCCが組織Aに 203.0.113.0/24 を割り当てる。
- 組織AはRIPE NCCからCA証明書を受け取る。
- その証明書により、「このプレフィックスの正当な管理者はAである」と証明可能になる
ROA ( Route Origin Authorization )
ROAは、「どのAS番号がどのプレフィックスをBGPで広報してよいか」を定義する情報です。
リソース証明書をもとに作成され、RPKIシステム全体の要となる存在です。
Prefix: 203.0.113.0/24
Origin-AS: 64500
MaxLength: 24
このROAは、「AS64500が203.0.113.0/24を広報することは正当である」という意味を持ちます。
一方で、他のAS ( 例:AS64501 ) が同じプレフィックスを広報した場合、その経路は「無効 ( invalid ) 」として判定されます。
ROAは発行組織自身が署名し、RPKIリポジトリに公開されます。
世界中のネットワーク機器はこのリポジトリを参照し、受け取ったBGP経路情報が正しいかどうかを照合します。
ROAキャッシュサーバ
ルータが直接RPKIデータをダウンロードして検証するのは非効率であり、スケーラビリティにも課題があります。
そのため、各ネットワークでは ROAキャッシュサーバ ( RPKI Validator ) を用意し、リポジトリから定期的にROA情報を取得・検証して整形した結果をルータへ配信します。
ルータはこのキャッシュサーバと通信する際に、RTRプロトコル ( RPKI to Router Protocol:RFC 6810 / RFC 8210 ) を使用します。
RTRは軽量なプロトコルであり、ルータが最新の検証状態 ( Valid / Invalid / NotFound ) をリアルタイムで受け取れる仕組みを提供します。
検証構成
ここでは、検証構成について説明します。
( ↓論理構成図 )

■ 親CA ( NLnet Labs RPKI Testbed )
NLnet LabsのRPKI Testbedは「親CA ( Parent CA ) 」として機能し、子CAであるKrillにリソース証明書を委任します。
この構成では、AS60000に対して「192.168.0.0/24」を認可するROAが発行されます。
■ 子CAおよびRPKIバリデータ ( Ubuntuサーバ上 )
Ubuntuサーバ上には、以下の2つの主要コンポーネントが動作している。
-
Krill ( Child CA ):
親CAからの委任を受け、AS60000向けのROAを発行する。 -
Routinator ( ROAs Validator ):
KrillからROAを取得・検証し、VRP ( Validated ROA Payloads ) を生成。
生成したVRPを RPKI-RTRプロトコル を通じてルータに配布し、ルータが経路の正当性を判断できるようにする。
■ BGPネットワーク
右側は CML 2.8 ( Cisco Modeling Labs ) 上のBGPネットワーク環境で、3台の仮想ルータが接続されている。
| ルータ | AS番号 | 機能 | 経路広告 |
|---|---|---|---|
| iol-0 | AS10000 | 検証対象ルータ。Routinatorと接続し、受信経路をRPKIで検証する。 | — |
| iol-1 | AS50000 | 不正な経路 ( 192.168.0.0/24 )を広告。 | 無効経路 ( Valid ) |
| iol-2 | AS60000 | 正しいな経路 ( 192.168.0.0/24 ) を広告。 | 正常経路 ( Invalid ) |
■ 目標:経路検証の結果
ルータ iol-0 は、Routinatorから取得したVRPに基づいて経路を検証する。
その結果:
- AS50000の経路 ( 192.168.0.0/24 ) → 不正 ( Invalid )
- AS60000の経路 ( 192.168.0.0/24 ) → 正しい ( Valid )
サーバ構築
Krillの構築 & セットアップ
以下のドキュメントに従い、Krillをインストールします。
sudo apt update
sudo apt install \
ca-certificates \
curl \
gnupg \
lsb-release
curl -fsSL https://packages.nlnetlabs.nl/aptkey.asc | sudo gpg --dearmor -o /usr/share/keyrings/nlnetlabs-archive-keyring.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/nlnetlabs-archive-keyring.gpg] https://packages.nlnetlabs.nl/linux/ubuntu \
$(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/nlnetlabs.list > /dev/null
sudo apt update
sudo apt install krill
次に、/etc/krill.confを編集し、外部からWebUIにアクセス可能にします。デフォルトでは、127.0.0.1からしかアクセスできない。
sudo vim /etc/krill.conf
ip "0.0.0.0" <=を追加
/etc/krill.confを編集後は、krillをリスタートします。
sudo systemctl restart krill
krillがうまく動作していれば、ブラウザからhttps://<Ubuntu IP>:3000にアクセスすることで以下のWebUIが表示される。
ここからはWebUIで設定を行なっていく。パスワードは、/etc/krill.conf内のadmin_tokenに記載されている。以下のコマンドで確認可能。
sudo grep -i "admin_token = " /etc/krill.conf
パスワードを入力すると、以下の画面に移行します。ここでは、親CA ( NLnet Labs RPKI Testbed ) とやり取りを行う、子CAを作成します。子CAの名前は適当で良いです。
CAを作成すると、以下の画面に移行します。
まず、親CAのリポジトリに接続する設定を行います。子CAのWebUIのRepository=>Add a repository を押下します。そして、Publisher Requestをコピーします。
次は、https://testbed.krill.cloud/ui/testbed/remove にアクセスし、Register Publisherに子CAでコピーしたPublisher Requestを貼り付けます。そして、Register publisherを押下します。
すると、レスポンスが表示されるので、これをコピーします。
子CAのWebUIに戻り、Repository Responseに貼り付けてConfirmを押下します。
設定がうまくいくと、以下のような画面になります。
次に、親CA ( NLnet Labs RPKI Testbed ) に作成した子CAを登録します。流れはリポジトリの時と同様です。まず子CAのWebUIのParents=>Add an additional parent を押下します。そして、Child Requestをコピーします。
次は、https://testbed.krill.cloud/ui/testbed/remove にアクセスし、Register CAに子CAでコピーしたChild Requestを貼り付けます。また、ASN ResourcesとIPv4 Resourcesを設定します。今回は雑にAS0-65535と0.0.0.0/0と設定し、REgister child CAを押下します。
子CAのWebUIに戻り、Parent Responseに貼り付けてConfirmを押下します。また、名前はNLnet_Labs_RPKI_Testbedとしています。
設定がうまくいくと、以下のような画面になります。
以上がKrillのセットアップとなり、これでROAを作成可能になります。
Routinatorの構築 & セットアップ
Krillと同様に以下のドキュメントに従い、Routinatorをインストールします。
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/nlnetlabs-archive-keyring.gpg] https://packages.nlnetlabs.nl/linux/ubuntu \
$(lsb_release -cs)-proposed main" | sudo tee /etc/apt/sources.list.d/nlnetlabs-proposed.list > /dev/null
sudo apt update
sudo apt install routinator
次に、/etc/routinator/routinator.confを編集し、外部からアクセス可能にします。デフォルトでは、127.0.0.1からしかアクセスできない。
sudo vim /etc/routinator/routinator.conf
# rtr-listen = ["127.0.0.1:3323"]
rtr-listen = ["0.0.0.0:3323"]
# http-listen = ["127.0.0.1:8323"]
http-listen = ["0.0.0.0:8323"]
Routinatorは、デフォルトだとインターネット上の経路情報を検証するために必要なRPKI ( Resource Public Key Infrastructure ) データを取得する際、5つの地域インターネットレジストリ ( RIR ) ——AFRINIC、APNIC、ARIN、LACNIC、RIPE NCC——が提供するトラストアンカーロケータ ( TAL ) に接続します。
このTALは、それぞれのRIRが運用するトラストアンカー証明書 ( 信頼の起点となる証明書 ) への“案内役”として機能し、RoutinatorがRPKI全体の認証情報 ( ROAやマニフェストなど ) を検出・検証するための出発点を提供するものです。今回は、NLnet Labs RPKI Testbedが提供するTALを使用するため、設定を変更する必要があります。
具体的には以下のオプションをつけた状態で起動させます。
sudo routinator --tal=nlnetlabs-testbed --no-rir-tals --config /etc/routinator/routinator.conf server
routinatorがうまく動作していれば、ブラウザからhttp://<Ubuntu IP>:8323にアクセスすることで以下のWebUIが表示されます。
また、MetricsにNLNETLABS-TESTBEDの情報が表示されるようになります。
以上がRoutinatorのセットアップとなり、これで子CAで作成したROAを参照することが可能になります。
ルータ設定
次はルータの設定です。
iol0
en
conf t
int e0/0
description TO-Ubuntu-Server
ip add 100.0.0.1 255.255.255.252
no shut
int e0/1
ip add 10.0.0.1 255.255.255.252
no shut
int e0/2
ip add 20.0.0.1 255.255.255.252
no shut
exit
router bgp 10000
neighbor 10.0.0.2 remote-as 50000
neighbor 20.0.0.2 remote-as 60000
bgp rpki server tcp 100.0.0.2 port 3323 refresh 60
iol1
en
conf t
int e0/1
ip add 10.0.0.2 255.255.255.252
no shut
int lo0
ip add 192.168.0.254 255.255.255.0
exit
access-list 1 permit 192.168.0.0 0.0.0.255
route-map AS10000-OUT permit 10
match ip address 1
set metric 10
exit
router bgp 50000
bgp router-id 1.1.1.1
neighbor 10.0.0.1 remote-as 10000
neighbor 10.0.0.1 route-map AS10000-OUT out
network 192.168.0.0 mask 255.255.255.0
address
iol2
en
conf t
int e0/2
ip add 20.0.0.2 255.255.255.252
no shut
int lo0
ip add 192.168.0.254 255.255.255.0
exit
access-list 1 permit 192.168.0.0 0.0.0.255
route-map AS10000-OUT permit 10
match ip address 1
set metric 20
exit
router bgp 60000
bgp router-id 2.2.2.2
neighbor 20.0.0.1 remote-as 10000
neighbor 20.0.0.1 route-map AS10000-OUT out
network 192.168.0.0 mask 255.255.255.0
以上の設定を無事に完了すると、iol0がiol1とio02とピアを張れていることがわかります。
show ip bgp summary
また、不正経路の方がMEDの値が小さいので、BGPテーブルを確認すると192.168.0.0/24のネクストホップが10.0.0.2となっていることがわかります。さらに、ROAが確認できないため、Not foundになっていることがわかります。
ROAの作成
ここからは、ROA作成していきます。
ROAの作成は子CAのWebUIから作成可能です。ROAs => Add ROAを押下します。
今回は、AS60000からの経路広告を正しい経路としたいので、ASNを60000、Prefixを192.168.0.0/24、Max Lengthを24とします。
無事に作成できると以下のように、作成したROAが表示されます。
Routinatorで確認すると以下のようにVRPが表示されるようになります。
確認
ROAの作成が完了したので、どのように変わったかを確認します。
iol0でshow ip bgpを行うと以下のような結果が返ってきます。先ほどとは、異なりAS60000から広告された経路情報を採用していることがわかります。また、先ほどまではNot foundでしたが、ROAを作成したことで経路情報にvalidとinvalidが表示されています。
おわりに
本検証では、CML上でKrillとRoutinatorを構築し、RPKIの基本的な動作を確認しました。
具体的には、
-
親CA ( NLnet Labs RPKI Testbed ) と子CA ( Krill ) の連携設定
-
子CAによるROA ( Route Origin Authorization ) の発行
-
RoutinatorによるROAの取得・検証 ( VRP生成 )
-
ルータ ( iol0 ) によるRPKI-RTRプロトコルを用いた経路検証
という流れを構築・動作確認しました。
検証の結果、RPKIに基づくROAの有無で経路選択が変化することを確認できました。
ROAが存在しない場合はNotFoundとして扱われ、不正な経路が選択される可能性があるが、ROAを発行するとRoutinatorがVRPとしてルータに配布し、BGP経路がValid/Invalidに分類され、正しい経路 ( Valid ) が選択されることを確認しました。
参考文献



























