インターネットにつながらない!

問題名

インターネットにつながらない!

概要

あなたはネットワーク開発部で働いています。すると、上司があなたに次のようなことを言ってきました。

最近、BGP unnumberedを使って大規模なネットワークを作るのが流行っているらしい。

BGP unnumberedを支える技術の一つにRFC5549という仕様があるらしくて、ちょっとそれを試す環境を作ってみたんだが、上手く通信できないんだ。

君はネットワークが詳しいらしいし、何が原因なのか調べてくれないかい?

上司はそういうと、メモとトポロジ図をおいてどこかに行ってしまいました。原因を解決してあげてください。

上司からのメモ

  • probrt, rt01, rt02には、FRRがインストールされている
  • それぞれのルータはmgmt VRFを切っているため、普通にはインターネットに接続することができない
    • apt updateをしたいならば、以下のようなコマンドを実行する必要がある
      • sudo ip vrf exec mgmt apt update
  • probrt, rt01には正しい設定が入っているので、それに合わせてrt02の設定を行ってほしい
  • 再起動しても、問題なく動作するように設定を行ってほしい

トポロジ図

前提条件

  • sv01, rt02のmgmt VRFに対する操作を行わない
    • 問題環境に接続できなくなる可能性があるので
    • eth0をmgmt VRFから外さない等
  • BGP以外の方法を用いて経路の設定を行わない

初期状態

  • sv01からインターネットにアクセスすることができない
    • 下記のコマンドが正常に実行できない
      • ping 1.1.1.1

終了状態

  • sv01からインターネットにアクセスすることができる
    • ここでは、下記のコマンド群が正常に実行でき、適切な結果を返す
      • ping 1.1.1.1
      • dig @1.1.1.1 A contest.ictsc.net
      • curl https://www.icttoracon.net
    • 解答には、これらのコマンドの実行結果も示してください
  • rt02を再起動しても、設定が維持されるようにしてほしい

想定解答

この問題では、三つの原因によってsv01のインターネットへの疎通性が失われていました。

  1. rt02がrt01に対し、Extended Nexthop capabilityを送信していない
  2. rt02でIP転送が許可されていない
  3. rt02にprobrtとの経路制御に利用するポリシーが設定されていない

これらを設定することでsv01からインターネットに通信することができるようになります。

1. rt02がrt01に対し、Extended Nexthop capabilityを送信していない

sudo vtysh を利用して以下の設定をFRRに投入します。

router bgp 65182
 neighbor fc00:1:: capability extended-nexthop

2. rt02でIP転送が許可されていない

以下の設定を/etc/sysctl.confに追記します。

net.ipv4.conf.all.forwarding = 1

3. rt02にprobrtとの経路制御に利用するポリシーが設定されていない

sudo vtysh を利用して以下の設定をFRRに投入します。

router bgp 65182
 no bgp ebgp-requires-policy

4. 設定の永続化とロード

1~3で行った設定を永続化したりロードしたりするために、以下のコマンドを実行します。

$ sudo sysctl -p
$ sudo vtysh -c "write" -c "clear ip bgp *"

これらの設定を行うことで、sv01からインターネットへ通信を行うことができるようになります。以下は、それぞれのコマンドの出力結果です。

(コマンドの出力結果は省略します)

解説

この問題は、BGP unnumberedの背景にあるRFC5549に関する設定やちょっとしたネットワークのトラブルが原因の問題でした。想定解法にもある通り、以下の三つの原因で問題が発生していました。

  1. rt02がrt01に対し、Extended Nexthop capabilityを送信していない
  2. rt02でIP転送が許可されていない
  3. rt02にprobrtとの経路制御に利用するポリシーが設定されていない

RFC5549(RFC8950)について

問題の詳しい解説に入る前に、RFC5549とは何なのかについて簡単に解説します。RFC5549とは、Multiprotocol BGP(MP-BGP)において、IPv4プレフィックスの経路のnexthopにIPv6アドレスを指定できるようにする拡張仕様です。もうちょっと噛み砕いた言い方をすると「172.16.0.0/24宛のパケットはfc00::1に転送してね」というような経路をBGPで広報できるようにする仕様です。

https://datatracker.ietf.org/doc/html/rfc5549

問題文中にもある通り、この仕様はBGP unnumberedという技術に利用されています。従来、BGPでは対向ルータのアドレスを指定する必要がありましたが、BGP unnumberedでは、その代わりに「eth1に接続されたルータ」のようにインターフェースを指定してBGPピアを指定することができるようになります。通信に使われるアドレスは、そのインターフェースから受信したRouter Advertisementに含まれるリンクローカルアドレスが利用されます。

BGP unnumberedを利用すると、大量のスイッチが収容されるデータセンターなどのネットワークにおいて、対向のスイッチのアドレスを意識することなく設定を行うことができるため、設定の簡素化を実現することができます。以下の記事でとても詳しく解説が行われているため、より詳しいことが知りたい場合には目を通してもらえたらと思います。

この背景を踏まえた上で、今回の問題について見ていきましょう。

想定解法の解説

まずは、sv01から1.1.1.1に対してパケットを送信するときに、どこまでパケットが到達しているのかを調べてみます。tracerouteを使って調べてみると、次のような結果が得られます。

user@sv01:~$ traceroute 1.1.1.1
traceroute to 1.1.1.1 (1.1.1.1), 30 hops max, 60 byte packets
 1  _gateway (172.16.0.254)  0.859 ms !N  0.820 ms !N *

これより、172.16.0.254(rt01)からDestination Net Unreachableが返っていていることが確認できます。問題設定から、rt02はrt01に対してdefault routeを広報しているはずです。このこととtracerouteの結果から、パケットが転送されない原因として以下のような原因が考えられます。

  1. そもそもrt02がdefault routeを広報していない
  2. rt02が広報している経路がおかしい
  3. rt02から広報した経路がrt01のFIBに入っていない

問題の設定よりrt01には適切な設定が入っているとされているため、三つ目の原因が起こることはないだろうと考え、上の二つの原因について考えていきます。

まずは、一つ目の原因について考えてみましょう。これを確かめるためには、rt02がrt01に対して広報している経路を確認すればよいです。その結果を以下に示します。これを見ると、Originating default network 0.0.0.0/0 とあるため、広報自体は行われていそうです。

rt02# show bgp ipv4 unicast neighbors fc00:1:: advertised-routes
BGP table version is 0, local router ID is 192.168.20.3, vrf id 0
Default local pref 100, local AS 65182
Status codes:  s suppressed, d damped, h history, * valid, > best, = multipath,
               i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes:  i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found

Originating default network 0.0.0.0/0

次に、二つ目の原因について考えてみましょう。rt02が広報した経路がおかしいことを確認するためにはいくつかの方法がありますが、ここでは実際にBGPパケットを見て確認してみましょう。rt02がrt01に対してdefault routeを広報しているUPDATEメッセージを見ると、NEXT_HOPに192.168.20.3というアドレスが指定されていることが分かります。ですが、rt01とrt02の間はIPv6のリンクで接続されているため、rt01はrt02にパケットを転送することができません。これらの情報から、RFC5549が利用できない状態になっているのではないかと推測することができます。

Frame 37: 155 bytes on wire (1240 bits), 155 bytes captured (1240 bits) on interface eth1, id 0
...
Internet Protocol Version 6, Src: fc00:2::, Dst: fc00:1::
    0110 .... = Version: 6
...
Border Gateway Protocol - UPDATE Message
    Marker: ffffffffffffffffffffffffffffffff
    Length: 46
    Type: UPDATE Message (2)
    Withdrawn Routes Length: 0
    Total Path Attribute Length: 22
    Path attributes
        Path Attribute - ORIGIN: IGP
            Flags: 0x40, Transitive, Well-known, Complete
                0... .... = Optional: Not set
                .1.. .... = Transitive: Set
                ..0. .... = Partial: Not set
                ...0 .... = Extended-Length: Not set
                .... 0000 = Unused: 0x0
            Type Code: ORIGIN (1)
            Length: 1
            Origin: IGP (0)
        Path Attribute - AS_PATH: empty
            Flags: 0x50, Transitive, Extended-Length, Well-known, Complete
                0... .... = Optional: Not set
                .1.. .... = Transitive: Set
                ..0. .... = Partial: Not set
                ...1 .... = Extended-Length: Set
                .... 0000 = Unused: 0x0
            Type Code: AS_PATH (2)
            Length: 0
        Path Attribute - NEXT_HOP: 192.168.20.3
            Flags: 0x40, Transitive, Well-known, Complete
                0... .... = Optional: Not set
                .1.. .... = Transitive: Set
                ..0. .... = Partial: Not set
                ...0 .... = Extended-Length: Not set
                .... 0000 = Unused: 0x0
            Type Code: NEXT_HOP (3)
            Length: 4
            Next hop: 192.168.20.3
        Path Attribute - LOCAL_PREF: 100
            Flags: 0x40, Transitive, Well-known, Complete
                0... .... = Optional: Not set
                .1.. .... = Transitive: Set
                ..0. .... = Partial: Not set
                ...0 .... = Extended-Length: Not set
                .... 0000 = Unused: 0x0
            Type Code: LOCAL_PREF (5)
            Length: 4
            Local preference: 100
    Network Layer Reachability Information (NLRI)
        0.0.0.0/0
            NLRI prefix length: 0
            NLRI prefix: 0.0.0.0
Border Gateway Protocol - UPDATE Message
    Marker: ffffffffffffffffffffffffffffffff
    Length: 23
    Type: UPDATE Message (2)
    Withdrawn Routes Length: 0
    Total Path Attribute Length: 0

これを確かめるために、rt01とrt02の間でどのような設定でBGPピアが確立しているのかを確認してみましょう。Extended nexthopの欄を見てみると、advertised and receivedではなく、receivedとなっています。この事から、rt02はRFC5549の動作に必要なExtended Nexthop capabilityをrt01に対して送っていないことが分かります。

rt02# show bgp neighbors fc00:1::
BGP neighbor is fc00:1::, remote AS 65182, local AS 65182, internal link
Hostname: rt01
  BGP version 4, remote router ID 172.16.0.254, local router ID 192.168.20.3
  BGP state = Established, up for 00:50:43
  Last read 00:00:43, Last write 00:00:43
  Hold time is 180, keepalive interval is 60 seconds
  Neighbor capabilities:
    4 Byte AS: advertised and received
    Extended Message: advertised and received
    AddPath:
      IPv4 Unicast: RX advertised and received
    Extended nexthop: received
      Address families by peer:
                   IPv4 Unicast
    Route refresh: advertised and received(old & new)
    Enhanced Route Refresh: advertised and received
    Address Family IPv4 Unicast: advertised and received
    Hostname Capability: advertised (name: rt02,domain name: n/a) received (name: rt01,domain name: n/a)
    Graceful Restart Capability: advertised and received
      Remote Restart timer is 120 seconds
      Address families by peer:
        none
  ...

FRRでExtended Nexthop capabilityを有効にするには、以下のコマンドを実行します。

rt02# conf t
rt02(config)# router bgp 65182
rt02(config-router)# neighbor fc00:1:: capability extended-nexthop

再度、rt01とrt02の間でどのようにBGPのピアが接続されているのかを確認してみましょう。今度は、advertised and receivedとなっています。これによって、rt01でもrt02から広報された経路を利用することができそうです。

BGP neighbor is fc00:1::, remote AS 65182, local AS 65182, internal link
Hostname: rt01
  BGP version 4, remote router ID 172.16.0.254, local router ID 192.168.20.3
  BGP state = Established, up for 00:00:13
  Last read 00:00:12, Last write 00:00:12
  Hold time is 180, keepalive interval is 60 seconds
  Neighbor capabilities:
    4 Byte AS: advertised and received
    Extended Message: advertised and received
    AddPath:
      IPv4 Unicast: RX advertised and received
    Extended nexthop: advertised and received
      Address families by peer:
                   IPv4 Unicast
    Route refresh: advertised and received(old & new)
    Enhanced Route Refresh: advertised and received
    Address Family IPv4 Unicast: advertised and received
    Hostname Capability: advertised (name: rt02,domain name: n/a) received (name: rt01,domain name: n/a)
    Graceful Restart Capability: advertised and received
      Remote Restart timer is 120 seconds
      Address families by peer:
        none

実際に、この設定を加えてからtracerouteを再実行してみると、次のように転送が続いていることが分かります。

user@sv01:~$ traceroute 1.1.1.1
traceroute to 1.1.1.1 (1.1.1.1), 30 hops max, 60 byte packets
 1  _gateway (172.16.0.254)  0.796 ms  0.880 ms  0.840 ms
 2  * * *
 3  * * *
 4  * * *

ですが、rt02でtcpdumpをしてみても、eth1で受信したパケットがeth2から送信されていないことが分かります。

user@rt02:~$ sudo tcpdump -ni eth1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
10:41:10.189211 IP 172.16.0.1 > 1.1.1.1: ICMP echo request, id 3, seq 1, length 64
10:41:11.191493 IP 172.16.0.1 > 1.1.1.1: ICMP echo request, id 3, seq 2, length 64
10:41:12.215471 IP 172.16.0.1 > 1.1.1.1: ICMP echo request, id 3, seq 3, length 64
10:41:13.725684 IP6 fe80::9ea3:baff:fe30:152e > ff02::1: ICMP6, router advertisement, length 56
^C
4 packets captured
4 packets received by filter
0 packets dropped by kernel

user@rt02:~$ sudo tcpdump -ni eth2
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth2, link-type EN10MB (Ethernet), capture size 262144 bytes
^C
0 packets captured
0 packets received by filter
0 packets dropped by kernel

Linuxでパケットが転送されない場合、以下のような原因が考えられます。

  1. そもそもパケットが転送される設定になっていない
  2. パケットの宛先への経路が存在しない
  3. iptablesなどでパケットがDROPしている

これらの原因を一つずつ考えてみましょう。一つ目の「そもそもパケットが転送される設定になっていない」というのは、sysctlを使って確かめることができます。以下に結果を示します。rt02はパケットが転送されるような設定になっていないことが分かります。

user@rt02:~$ sudo sysctl -a | grep ipv4 | grep forwarding
net.ipv4.conf.all.bc_forwarding = 0
net.ipv4.conf.all.forwarding = 0
net.ipv4.conf.all.mc_forwarding = 0
net.ipv4.conf.default.bc_forwarding = 0
net.ipv4.conf.default.forwarding = 0
net.ipv4.conf.default.mc_forwarding = 0
net.ipv4.conf.eth0.bc_forwarding = 0
net.ipv4.conf.eth0.forwarding = 0
net.ipv4.conf.eth0.mc_forwarding = 0
net.ipv4.conf.eth1.bc_forwarding = 0
net.ipv4.conf.eth1.forwarding = 0
net.ipv4.conf.eth1.mc_forwarding = 0
net.ipv4.conf.eth2.bc_forwarding = 0
net.ipv4.conf.eth2.forwarding = 0
net.ipv4.conf.eth2.mc_forwarding = 0
net.ipv4.conf.lo.bc_forwarding = 0
net.ipv4.conf.lo.forwarding = 0
net.ipv4.conf.lo.mc_forwarding = 0
net.ipv4.conf.mgmt.bc_forwarding = 0
net.ipv4.conf.mgmt.forwarding = 0
net.ipv4.conf.mgmt.mc_forwarding = 0

また、FRRの設定からも転送が有効になっていないことが確認できます。

rt02# show running-config
Building configuration...

Current configuration:
!
frr version 8.1
frr defaults traditional
hostname rt02
log syslog informational
no ip forwarding
no ipv6 forwarding
service integrated-vtysh-config

この原因を解決するためには、以下のようなコマンドを実行すればよいです。

user@rt02:~$ echo 'net.ipv4.conf.all.forwarding=1' | sudo tee -a /etc/sysctl.conf
net.ipv4.conf.all.forwarding=1
user@rt02:~$ sudo sysctl -p
net.ipv4.conf.all.forwarding = 1

次に、二つ目の「パケットの宛先への経路が存在しない」について考えてみましょう。Linuxのルーティングテーブルを表示させてみると、default routeが存在していないことがわかります。この経路はprobrtから広報されているはずなのですが、何らかの理由で経路がルーティングテーブルに入っていないことが分かります。

user@rt02:~$ ip route show
10.0.0.0/24 dev eth2 proto kernel scope link src 10.0.0.1
172.16.0.0/24 nhid 214 via inet6 fc00::1 dev eth1 proto bgp metric 20

BGPのピアの様子を次のコマンドで確認してみると、10.0.0.2(probrt)とやり取りしている経路(PfxRcd, PfxSnt)の欄に(Policy)と書かれていることが分かります。多くのルータでは、eBGPピアに経路を広報する際に、どんな経路を送信/受信してよいかを示したprefix-listを付ける必要があります。今回はその設定が抜けているため、probrtから広報された経路をrt02で受信することができなくなっていました。

rt02# show bgp summary

IPv4 Unicast Summary (VRF default):
BGP router identifier 192.168.20.3, local AS number 65182 vrf-id 0
BGP table version 1
RIB entries 1, using 184 bytes of memory
Peers 2, using 1446 KiB of memory

Neighbor        V         AS   MsgRcvd   MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd   PfxSnt Desc
10.0.0.2        4      65971       118       118        0    0    0 00:50:16     (Policy) (Policy) N/A
fc00:1::        4      65182       121       125        0    0    0 00:14:14            1        1 N/A

Total number of neighbors 2

この問題を解決するためには、以下の二つの方法が考えられますが、ここでは簡単に最初の方法で解決をします。

  1. eBGPでもprefix-list無しで経路を送受信できるようにする
  2. prefix-listを設定する
rt02# conf t
rt02(config)# router bgp 65182
rt02(config-router)# no bgp ebgp-requires-policy

この設定を行った後に、probrtとのBGPピアをリセットすると問題が解決します。

rt02# clear ip bgp 10.0.0.2

補足

FRRのIP転送の挙動について

解答を送信してきたほぼ全てのチームで、vtyshから以下のコマンドを実行してIP転送を許可していました。

ip forwarding

このコマンドを実行すると、確かにIP転送されるようになりますし、writeすると永続化しているように感じるのですが、実際には再起動をしてもIP転送は無効の状態で起動します。この奇妙な挙動にハマって永遠と270点で採点されたチームもいるかと思います。問題として意図したものではないのですが、ハマるポイントなので注意する必要があります。

RFC5549とBGP unnumberedについて

よく誤解されるポイントなのですが、RFC5549とBGP unnumberedは別のものを指しています。

RFC5549は「MP-BGPでIPv4のプレフィックスのnexthopにIPv6アドレスを指定できるようにする仕様」のことを指しています。

それに対し、BGP unnumberedは「RFC5549やRAによるアドレス学習を用いてBGPピアをインターフェース名から自動で設定する技術」のことを指しています。unnumberedという言葉は、インターフェースに明示的なアドレスを設定しないことから来ています。

そのため、今回の問題のようにIPv6アドレスを設定しているような場合には「BGP unnumberedを利用している」と表現するのは適切ではないです。問題文中でも上司が「BGP unnumberedを支える技術の一つにRFC5549という仕様があるらしいんだが」というように説明をしています。

問題文中のRFC5549という表記について

ここまで長々とRFC5549について解説してきましたが、現在ではRFC5549はobsoluteされており、RFC8950という仕様になっています。変更点は非常に小さなものなので、大枠は変わらないのですが、問題文中では古い番号を参照し続けています。解説では問題文と一貫性を保つために、RFC5549と呼び続けていますが、この点について注意してもらえたらと思います。

採点基準

  • (40%) Extended Nexthop capabilityがないことに気づき、設定を行う
  • (40%) IP転送が許可されていないことに気づき、設定を行う
    • vtyshで ip forwarding を実行した場合でも、sysctlをいじった場合でも等しく点数を与えています
  • (20%) probrtからのdefault routeを受信できるように設定を行う
    • no bgp ebgp-requires-policy でも明示的にprefix-listを書いた場合でも等しく点数を与えています
  • (-10%) FRRの設定が永続化されていない
  • (-10%) IP転送の設定が永続化されていない

作問者からのコメント

本当はちゃんとBGP unnumberedな問題として出題したかったのですが、環境等の制約からExtended Nexthopに関する部分だけで出題することになりました。この問題の背景には、これまでのデータセンターネットワークの発展の軌跡が隠れているため、楽しんでいただけたならとても嬉しいです。