ICTSC2025 本戦 問題解説: [3061] ネットワークって難しいね

問題文

概要

冗長構成のルーター(vyos-1, vyos-2)を構築し、バックエンドのサーバーとの間でBGPピアリングを完了させました。しかし、クライアントからサーバーのVIP(172.16.61.100)へPingを実行しても、全く応答がありません。 通信が正常に行えるように復旧させてください。

制約

  • ファイアウォールのルール(set firewall 階層)を変更・削除してはならない。(セキュリティ要件のため)
  • Static Routeを新たに追加してはならない。
  • VRRPの優先度(Priority)を変更し、Master/Backupを切り替えてはならない(vyos-2がMasterのままとすること)。
  • server及びclientの設定は一切変更してはならない。
  • 送信元IPアドレスの変換(Source NAT / Masquerade等)を行ってはならない。
  • 両vyosサーバ共にreboot後も終了状態が維持されていること

初期状態

  • clientからping 172.16.61.100を実行すると、100%パケットロスとなり通信が成立しない。

終了状態

  • clientからping 172.16.61.100を実行すると、Echo Replyが正常に返り、パケットロスが0%となる。

  • `vyos-2 をダウンさせた状態においても、clientからserver(172.16.61.100)へのPing通信が成立すること。


解説

  1. ルーティングの破綻(AD値の逆転)の特定と修正

    初期状態では、VIPへのPingが vyos-2 に到達した後、迷子になっています。vyos-1 のルーティングテーブルを確認すると、BGPで学習すべきVIP(172.16.61.100/32)の経路が、vyos-2 からOSPF経由で流れてきた経路によって上書きされています。これはVyOSにおけるAD値が OSPF (110) < iBGP (200) と評価されるためです。
    これを解消するため、VIPの経路がOSPFへ再配布されないようにプレフィックスリストとルートマップを作成し、両方のルーターの redistribute bgp に適用する必要があります。

  2. 非対称ルーティングとステートフルFWの競合解決

    経路のループを解消しても、Pingは通りません。パケットキャプチャやFWのログ(Rule 20: invalid)を確認すると、戻りパケットが vyos-1 で破棄されていることがわかります。
    行きのパケットはVRRP Masterである vyos-2 を通りますが、サーバー側はBGPのタイブレーカー(ルータIDが若い順)に従い、戻り経路として vyos-1 を選択します。これにより非対称ルーティングが発生し、行きのセッション情報を持たない vyos-1 のFWがパケットを不正とみなしてDropしています。
    解決策として、FWのルールを削除するのではなく、vyos-1 側のBGP経路広報時にMetric(MED)を悪化させ、サーバーに vyos-2 を選ばせるトラフィックエンジニアリングを行うのが正攻法です。

また、この問題は制作者が想定していたトラブルではなく、天然でできたトラブルのため、解法が複数存在する可能性があります。

想定解法

正攻法を下記に残してあります。

まずclientから ping 172.16.61.100を送信します。すると

root@3061-client:/home/ictsc# ping 172.16.61.100
PING 172.16.61.100 (172.16.61.100) 56(84) bytes of data.
^C
--- 172.16.61.100 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2033ms

という結果になり通らないことが確認できます。

次に、tracerouteを実行します

ictsc@3061-client:~$ traceroute 172.16.61.100
traceroute to 172.16.61.100 (172.16.61.100), 30 hops max, 60 byte packets
1  10.0.61.3 (10.0.61.3)  0.811 ms  0.728 ms  0.631 ms
2  * * *
3  * * *
4  * * *
5  * * *
6  * * *
7  *
 以下略

という結果が返ってくるため、vyos-2へ届いていることは確認できます。

消失したパケットの行方を知るため、vyos-2へログインします。

こちらで調査のため、 show ip route 172.16.61.100 を実行しますが、

ictsc@3061-vyos-2:~$ show ip route 172.16.61.100
Routing entry for 172.16.61.100/32
  Known via "bgp", distance 200, metric 0, best
  Last update 00:26:49 ago
  * 172.16.61.1, via eth1, weight 1

という結果になり、異常はみられません。ここで、冗長構成を組んでいるvyos-1へログインし、調査します

ictsc@3061-vyos-1:~$ show ip route 172.16.61.100
Routing entry for 172.16.61.100/32
  Known via "ospf", distance 110, metric 20, best
  Last update 00:28:18 ago
  * 10.0.61.3, via eth2, weight 1

この結果から、BGPで直接学習すべきVIPの経路が、vyos-2 から流れてきたOSPF経路によって上書きされている現状に気づけます。両ルーターの再配布設定を見に行きます。

ictsc@3061-vyos-1:~$ configure
[edit]
ictsc@3061-vyos-1# show protocols ospf
 area 0 {
     network 10.0.61.0/24
 }
 redistribute {
 }
 
 ictsc@3061-vyos-2:~$ configure
[edit]
ictsc@3061-vyos-2# show protocols ospf
 area 0 {
     network 10.0.61.0/24
 }
 redistribute {
     bgp {
     }
 }

この結果から、vyos-1はそもそも redistribute bgpの設定がなく、vyos-2は設定自体はあるが、ルートマップが適用されていないことが確認できます。

vyos-2 がフィルタ無しで再配布しているため、VIPの経路までvyos-1へ流れ込み、AD値の逆転を引き起こしていること、vyos-1 に再配布設定が入っていないのは、冗長構成の設計として明らかに設定漏れです。
これを修正するために、VIPを除外するフィルタを作成し、vyos-2の既存設定を修正するとともに、vyos-1には欠落していた設定を正しく追加します。

  • vyos-1

    configure
    
    set policy prefix-list FILTER-VIP rule 10 action 'deny'
    set policy prefix-list FILTER-VIP rule 10 prefix '172.16.61.100/32'
    set policy prefix-list FILTER-VIP rule 20 action permit
    set policy prefix-list FILTER-VIP rule 20 prefix 0.0.0.0/0
    set policy prefix-list FILTER-VIP rule 20 le 32
    
    set policy route-map RMAP-BGP-TO-OSPF rule 10 action permit
    set policy route-map RMAP-BGP-TO-OSPF rule 10 match ip address prefix-list 'FILTER-VIP'
    
    # 欠落していた再配布設定をフィルタ付きで追加
    set protocols ospf redistribute bgp route-map 'RMAP-BGP-TO-OSPF'
    
    commit
    save
    exit
    
  • vyos-2

    configure
    set policy prefix-list FILTER-VIP rule 10 action 'deny'
    set policy prefix-list FILTER-VIP rule 10 prefix '172.16.61.100/32'
    set policy prefix-list FILTER-VIP rule 20 action permit
    set policy prefix-list FILTER-VIP rule 20 prefix 0.0.0.0/0
    set policy prefix-list FILTER-VIP rule 20 le 32
    
    set policy route-map RMAP-BGP-TO-OSPF rule 10 action permit
    set policy route-map RMAP-BGP-TO-OSPF rule 10 match ip address prefix-list 'FILTER-VIP'
    
    # 既存の再配布にフィルタを適用
    set protocols ospf redistribute bgp route-map 'RMAP-BGP-TO-OSPF'
    
    commit
    save
    exit
    

確認のため、 show ip route 172.16.61.100 コマンドで、両ルーターが正しく直接サーバを向いているか確認します

ictsc@3061-vyos-1:~$ show ip route 172.16.61.100
Routing entry for 172.16.61.100/32
  Known via "bgp", distance 200, metric 0, best
  Last update 00:06:50 ago
  * 172.16.61.1, via eth1, weight 1

ictsc@3061-vyos-2:~$ show ip route 172.16.61.100
Routing entry for 172.16.61.100/32
  Known via "bgp", distance 200, metric 0, best
  Last update 00:46:58 ago
  * 172.16.61.1, via eth1, weight 1

ここでclientから ping 172.16.61.100を実行してみます

ictsc@3061-client:~$ ping 172.16.61.100
PING 172.16.61.100 (172.16.61.100) 56(84) bytes of data.
^C
--- 172.16.61.100 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1006ms

まだこの時点では通りません。

再度tracerouteを実行します

ictsc@3061-client:~$ traceroute 172.16.61.100
traceroute to 172.16.61.100 (172.16.61.100), 30 hops max, 60 byte packets
 1  10.0.61.3 (10.0.61.3)  0.753 ms  0.639 ms  0.563 ms
 2  * * *
 3  * * *
 4  * * *
 5  * * *

ルーティングテーブルは直したのにも関わらず、パケットが通らないので、パケットをキャプチャします

clientからpingを送信した状態でvyos-2のeth1にて、 monitor traffic interface eth1 コマンドで確認します。

ictsc@3061-vyos-2:~$ monitor traffic interface eth1
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), snapshot length 262144 bytes
02:49:20.768803 IP 10.0.61.1 > 172.16.61.100: ICMP echo request, id 3242, seq 17, length 64
02:49:21.792523 IP 10.0.61.1 > 172.16.61.100: ICMP echo request, id 3242, seq 18, length 64
02:49:22.816829 IP 10.0.61.1 > 172.16.61.100: ICMP echo request, id 3242, seq 19, length 64
02:49:23.840766 IP 10.0.61.1 > 172.16.61.100: ICMP echo request, id 3242, seq 20, length 64

リクエストは届いているが、リプライが確認できないのでvyos-1も確認します(monitor traffic interface eth1)

tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), snapshot length 262144 bytes
02:57:55.373199 IP 172.16.61.100 > 10.0.61.1: ICMP echo reply, id 3250, seq 1, length 64
02:57:56.417441 IP 172.16.61.100 > 10.0.61.1: ICMP echo reply, id 3250, seq 2, length 64
02:57:57.441481 IP 172.16.61.100 > 10.0.61.1: ICMP echo reply, id 3250, seq 3, length 64
02:57:58.465696 IP 172.16.61.100 > 10.0.61.1: ICMP echo reply, id 3250, seq 4, length 64
02:57:59.489809 IP 172.16.61.100 > 10.0.61.1: ICMP echo reply, id 3250, seq 5, length 64
02:58:00.513940 IP 172.16.61.100 > 10.0.61.1: ICMP echo reply, id 3250, seq 6, length 64

こちらに届いていることが確認できます。

このことからvyos-1でパケットが破棄されていることがわかります。

パケットを破棄している理由をファイヤウォールを確認して証明します

ictsc@3061-vyos-1:~$ show firewall ipv4 forward filter
Ruleset Information

---------------------------------
ipv4 Firewall "forward filter"

Rule     Action    Protocol      Packets    Bytes  Conditions
-------  --------  ----------  ---------  -------  -----------------------------------------
10       accept    all                12     1044  ct state { established, related }  accept
20       drop      all                98     8424  ct state invalid
30       accept    all               144     9000  iifname "eth2"  accept
default  drop      all                 0        0

client側からpingを送れば送るほど、Rule20のPacketsが増えることが確認できます。

ictsc@3061-vyos-1:~$ show firewall ipv4 forward filter
Ruleset Information

---------------------------------
ipv4 Firewall "forward filter"

Rule     Action    Protocol      Packets    Bytes  Conditions
-------  --------  ----------  ---------  -------  -----------------------------------------
10       accept    all                12     1044  ct state { established, related }  accept
20       drop      all               100     8592  ct state invalid
30       accept    all               144     9000  iifname "eth2"  accept
default  drop      all                 0        0

原因が非対称ルーティングであると証明されたため、サーバからの戻りパケットを行きと同じvyos-2へ向かわせるよう、vyos-1に入りBGPの経路属性を操作します。

configure

# vyos-1からサーバへ広報する経路のMetric(MED)を100に設定
set policy route-map RMAP-BGP-OUT rule 10 action permit
set policy route-map RMAP-BGP-OUT rule 10 set metric 100

# サーバ(172.16.61.1)への送信(export)ポリシーとして適用
set protocols bgp neighbor 172.16.61.1 address-family ipv4-unicast route-map export RMAP-BGP-OUT

compare
commit
save
exit

この設定完了後、clientにて ping 172.16.61.100 を実行します。

ictsc@3061-client:~$ ping 172.16.61.100
PING 172.16.61.100 (172.16.61.100) 56(84) bytes of data.
64 bytes from 172.16.61.100: icmp_seq=1 ttl=63 time=1.81 ms
64 bytes from 172.16.61.100: icmp_seq=2 ttl=63 time=1.22 ms
64 bytes from 172.16.61.100: icmp_seq=3 ttl=63 time=1.02 ms
^C
--- 172.16.61.100 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 1.021/1.350/1.805/0.332 ms

採点基準

  • clientからVIP(172.16.61.100)へのPingが成功していること。: 50%

  • vyos-2 をダウンさせた状態においても、clientからserver(172.16.61.100)へのPing通信が成立すること。: 50%

注意点

  • 制約に則っていなければ0点

講評

解法が色々あって自分が逆に勉強になったなーと思った問題でした。
もっと制約等で厳しくすべきだと考えました。