セキュリティ・キャンプ2021に応募し選考が通りましたので課題を晒してみます。
皆やっているので便乗です。
セキュリティキャンプとは
セキュリティキャンプとはなんだろうという人はIPAのページをご覧ください。
簡単に言うと学生を対象とした高度な技術教育+倫理教育のために国が行っている行事です。
第一線で活躍する講師の方がセキュリティに限らず様々なテーマで講義を行います。
学生は講義を選んで応募が可能ですが、応募課題があり選考に通る必要があります。
本来はオフラインで4泊5日で行うものですが最近はコロナの影響でオンラインとなっています。
そしてなんと完全無料です。
参加講義
今年が学生最後の22歳ということで滑り込みです。
存在は知っていましたが、オフラインで泊まりは嫌でずっと応募せずにいましたがオンラインとなったので応募してみました。
(講師の方のTwitterでコースに興味を持ったのが大きな理由です)
私が応募したのは集中コースのZ4である「BGPを実装して学ぶルーティングプロトコル」で、
BGPを学びながらフルスクラッチでBGPを実装し、OSSのFRRoutingと相互接続を行うというものです。
今後内定先企業でもBGPを使うため勉強にちょうど良いので応募しました。
結果
先に結果からお伝えすると、無事に選考に通りました。
当時あまり時間は取れなかったのですが、深夜ガッと課題に取り組みなんとか。。。って感じです。
課題回答
熱意をもって手を動かしてくれるかを測っていると課題に記載があったため、
VMを作成して実際にトラシューしながら下のようにまとめました。
というより実際にVMで動かさないと課題に回答できなさそうですが。
課題の内容はIPAのページのZトラックにあります
課題でいろいろと初知りなものがありました。
netnsでinterfaceなどを分離できるなどなど
```
# セキュリティキャンプ2021 課題
※MarkDownで記入しております。
## 調査課題: 動機や経験
***プログラミングについて***
1. Pythonを使ったTracerouteの動作確認
Pythonの標準ライブラリであるSocket、
パケット操作ライブラリであるScapyを利用してTracerouteの動作確認をしました。
WindowsとLinuxにおいてUDPであったりICMPであったり動作が異なる点を確認できました。
詳細は自分のブログにまとめてありますので読んでいただければ幸いです。
このプログラムはTracerouteで取得した値をデータベースに入れて可視化してみたいという思いから作成したものです。(まだ可視化まではできていませんが。。。)
動作は単純でTTLを1からスタートし、インクリメントしながら対象の宛先に到達したら動作終了します。作成してみて感じた点は非常に高速であることです。
WindowsではICMPを3回送信しており、リプライがない場合の待ち時間が非常に長く感じました。またLinuxで利用されるTracertではUDPの33434付近を利用している点も知ることができたので良かったと思います。
2. Discordから家のサーバを起動するBot
このプログラムは家の外からでも家のサーバの電源を入れたい。
スマホからでも楽に電源を入れたいという個人的な課題から作成したものです。
Discord.pyというライブラリを使ってDiscordというチャットツール上で動作するものです。
このBotに対して`!wol`と送信すると、自宅のサーバのどれにしますか?と表示されます。
その中から対象のサーバを選択して番号を送信するとマジックパケットが送信され、
Wake on LANでサーバが起動します。
マジックパケット送信後30秒毎にPingによる疎通確認を行い、正常に疎通するとActiveと返されます。これは自宅の同じネットワークセグメントのRaspberryPiで常時動かしています。
しかし、最近家のネットワーク構成を変更したことから他のセグメントからマジックパケットを動作させたいと考えており、検討中です。(未着手)
3. rancidを使ったコンフィグの自動バックアップ
コード等は利用していませんが、rancidを利用して自宅の機器のコンフィグを保存しております。crondによる定時実行ですが、コンフィグに変化があると自動的にコミットされ、Gitlabにプッシュされます。
4. まとめ
普段からあまり多くのコードを書くことはありませんが、今後自動化やモニタリング、ソフトウェア管理のネットワークも触る機会が増えていくと思うのでPythonを中心に学習していきます。現状は作りたいものがあれば調べながら実装していましたが、一度基礎から学んでみようかと思っています。
また、コードだけでなくRouting Softwareについて、ProxmoxにVyOSを入れてはいますがまだまだ知識が乏しいです。ホワイトボックススイッチであったり、K8sのCNIであるCalicoやFlannelなどでもネットワークが絡んでいるようなのでこのあたりの知識と技術力も高めていきたいと考えています。
***ネットワークについて***
1. 自宅ネットワーク
自宅環境を整えています。
メインのPCのデフォルトゲートウェイはSophos XG Firewallを利用しており、
Cisco891fj, Catalyst2960G等, YAMAHARTX1200(L2TP/VPN), Aironet(無線)を利用しています。また、最近自宅ラボの構成を変更しました。真面目に設計してみようと頑張ってみたものの考慮漏れが多くうまく動かないこともありました。
冗長性を確保しようと考えて見ましたが、LAGに対応していない機種であったり、VRRPに対応していなかったりいろいろありました。自宅のネットワークを作るにあたって、図を作成しましたのでご覧いただければ幸いです。
サーバはProxmoxを利用しています。Bonding+Trunkで構成しており、
LinuxBridgeでVLAN毎にセグメントを分けています。
検証用のネットワークはVMであるEve-ngともつながっており、外のネットワークとエミュレータの疎通も可能です。
3. まとめ
私はネットワークエンジニアとして働くことが確定しており、スキルアップのために
今回応募させていただきました。特にBGP周りは今まで全く触れて来なかった部分ですので、
今回のセキュリティ・キャンプをきっかけに知識を深め、今後に役立てていきたいです。
何卒宜しくお願いいたします。
## 課題z4-1: ネットワーク技術の基本 (ルーティングプロトコルとSDN)
- ルーティングプロトコルについて
インターネット全体を見たときに、ネットワークとは組織や国、同一ポリシーなどの集合体(ASの集合)であり、これらが集まり経路を交換することで世界全体への疎通が行えるようになる。
当然ネットワークはすべて無料ではなくフルルートを所持するような大きな会社にお金を払うこともあれば、利害関係の一致で協力することもある。このようにネットワークは技術だけでなく政治や金などの要素も大きく関係する。
これらのASとASを結ぶには一つのルールに沿う必要がある。そのルールの一つであるプロトコルには様々なルーティングプロトコルが存在する。
プロトコルには様々な役割があり、上の各ASを結ぶEGPであるBGP, 同一AS内を管理するIGPであるOSPF, RIP, IS-IS、 Ciscoのみで動作するEIGRPなど様々。
プロトコルの動作についてはディスタンスベクタ型やリンクステート型などアルゴリズムも異なる。
- OSPFについて
OSPFはリンクステート型であり、多く利用されているプロトコル。
EIGRPのようにベンダーロックインでは無いため、冗長性の観点でも複数メーカー製品で利用できるため設計しやすいと思われる。
リンクステートという名前の通り、接続情報であるLSAを交換しあい、その情報から経路を決定する。また、経路を決定するのに利用するコストについては帯域も考慮するため速度についても最適な経路を選択してくれる。
ある程度大きな規模になるとLSAの交換やコンバージェンス時間も遅くなり、管理するテーブルも大きくなりCPU使用率が上がる。そこで、エリアという概念でさらに小さいグループに分ける。そのエリア間にあるABRでルートの集約を行うことでテーブルのサイズも小さくすることができる。また、LSAにも種類があり、各セグメントに置いてDR, BDRを選出し、LSAのパケットを減らすように工夫されている。
このようにメリットは多いが、デメリットとして、リソースを多く使うので機器の選定と
事前にしっかりとした設計を行わないとSPF計算による障害や負荷が上がってしまう点が挙げられる。
- RIPについて
RIPはディスタンスベクタ型であり、メトリックというTTLの数で経路を決定する。
RIPv2はVLSMに対応している。
このメトリックを利用する場合帯域が考慮されないため、遅い経路が選択されてしまう可能性がある。
また、メトリックは最大16までという制限があるため16ホップ以上のネットワークでは動作しない。
RIPは隣接情報の交換を繰り返すため収束までに時間がかかり、ループが発生しやすい仕組みとなっている。
このループを防ぐための仕組みも存在する。
経路情報の送信元ルータにはアナウンスしないスプリットホライズン、
経路情報の送信元ルータにはメトリックを16にして返すポイズンリバース。
OSPFと比較するといいところが少ないように見えるが、SPFの計算がいらない点や
動作が単純であることから小規模なネットワークでは利用されることもある。
- BGPについて
BGPは上のIGPとは違いAS間を繋ぐ事がメインであり、世界という単位で見たときに各組織を繋ぐ役割を担っている。
つい最近BGPについては簡単に学びアウトプットしたのでこちらをご覧いただければ幸いです。
- SDNについて
SDNについては私は全く知見がありません。。。
ここは学びたいと思いつつもなかなか手を出しにくい領域です。
OpenFlowを利用してコントロールプレーンとデータプレーンに機能を分離し、
コントロールプレーンを集中制御することで制御の自動化や一元管理が可能となり、
様々なAPIを活用することができるのも魅力の一つ。
Ciscoのソリューションの一つにACIというものがあり、ネット上で様々な意見がありますが、
使いこなせればかなり便利な仕組みだと考えています。
このあたりを学ぶのにおすすめがあればぜひ教えていただきたいです。
## 課題z4-2 (調査): ルーティング技術1
### 4-2-1: Static Routing v.s. Dynamic Routing
Static RoutingとDynamic Routingの違いとして、
まずは手動で追加するものであるか、自動的に追加されるものであるかが挙げられる。
(自動と言っても対象のインターフェース等指定は必要になる)
大規模なネットワークや変化の多いネットワークではDynamic
規模が小さく変化のないネットワーク、意図的にルートを残したい場合はStaticが使われる。
Dynamic Routingの利点
- 規模の大きいネットワークにおいて、各機器に多くの設定を入れる手間がない。
- ルーティングアルゴリズムを利用して最適な経路を選択してくれる。
- 障害時にDynamic Routingは自動的に代替パスを取得するため影響が小さい。
Dynamic Routingの欠点
- リソースをより多く使う。
- 設計を正しく行わないと意図しない経路を通る可能性がある。
- インターフェースに不具合があると計算が多く行われる。
- 間違った設定を流し込むと影響範囲が広い。
Static Routingの利点
- Staticで指定するため意図した経路を通るように確実性がある。
- 変化のないネットワークでは安定する。
- 計算のリソースを使わないため軽量。
- 意図的にRoutingテーブルに残したい場合にも使える。
- NullにStatic Routingを行いルーティングループを防ぐ設定も行う。
Static Routingの欠点
- 規模の大きいネットワークでは設定が多く困難
- 冗長化が難しい(floating Staticという手はあるが)
- ネクストホップの指定方法により動作が異なる点には注意が必要
BGPがOSPFやIS-ISと違う点については4-1課題で述べたため省略するが、
AS間の経路を交換するEGPであり、純粋な技術だけでなく組織の規模や課金も考慮した上で
トランジットやピアを行う。複数ルータがある場合はAS内でもiBGPによるフルメッシュ接続が行われる。
### 4-2-2: RIB v.s. FIB
RIBとFIBについては存じ上げませんでした。
自分なりに調査した内容では、
RIBとは各Routing Protocol, Static Routeから得たRoutingの情報を取り扱うもので、
経路情報がDRAMに保存されている。データプレーンとコントロールプレーンに分ける場合、
コントロールプレーンに該当する。
FIBとはRIBから作成される転送に特化させたテーブルであり、ツリー構造になっている。
宛先ネットワークプレフィックスとネクストホップ情報が含まれる。
CiscoではこのFIBとAdjacencyテーブル(ARPCacheから)をCEFにまとめ、
CEFをハードウェア処理することで高速転送ができる。CEFはデータプレーンに該当する。
実際にパケットを転送する際はこのテーブルを参照する。
コントロールプレーンのソフトウェア処理はCPU、
データプレーンのハードウェア処理はASICを指す。
Best path selectionについて、BGPはいくつもの属性を持っており、
優先度の高い順番に評価し、複数経路の中から最適なパスを見つける。
具体的には以下のように評価される。
```
1 ネクストホップへの到達性がない場合は無視(IGPルートを持っているか)
2 CiscoのWeightパラメータが大きいルート
3 Local Preference属性の高いルート
4 AS_PATH属性のリストが短いルート
5 ORIGIN属性のタイプが最も低いルート
6 MULTI_EXIT_DIC属性の低いルート
7 iBGPよりもeBGPで学習したルート
8 ネクストホップへ最小のIGPメトリックを持つルート
9 Router IDが小さいルート
```
Administrative DistanceはAD値とも呼ばれ、経路の信頼度を表し、
複数の経路が合った場合にAD値が低い経路が選択される。
AD値よりもロンゲストマッチが優先されるので同じプレフィックスであることは必須。
プロトコル毎にAD値のデフォルト決まっているが、メーカーに寄って異なる場合があるので注意が必要。このAD値を変更することでfloatingが可能になる。
イメージ(想像)
- RIB
```
Prot Addr Pre Next Inter
OSPF 192.168.0.0 /24 172.16.1.1 Gi0/1
```
- FIB
```
Addr Pre AdjacencyPointer
192.168.0.0 /24 172.16.1.1
```
### 課題z4-2-3: L3 Forwarding and Nexthop
C1にて10.3.0.2宛にPingコマンドを実行するとまずはC1の持つRoutingtableを確認する。
直接接続のネットワークセグメントではないため、デフォルトルートを設定した10.1.0.1に送信する。送信する前にARPCacheがあるか確認し、ない場合は10.1.0.1のMACアドレスを調べるためにARPを送信する。R1はARPに応答し、C1は得たMACアドレスをL2ヘッダの宛先MACとして送信する。L3の宛先はC3のIPをセットしている。
R1に届くと自分のMACアドレス宛であることを確認した後L3の宛先を確認する。
R1のRouting Tableから、ロンゲストマッチで一致するStatic Routeがあることを確認し、R1は10.255.1.2に送信する。このとき、RoutingテーブルとMACアドレステーブルを確認し、転送するインターフェースも確認。送信元MACアドレスと宛先MACアドレスを書き換え転送。
R2に到達すると直接接続のIPアドレス宛であることから、該当のインターフェースに転送。
C3は自分宛のEcho Requestであることを確認し、Echo Replyを返す。
帰りも行きと同様だが、すでにMACアドレスの学習は済んでいるためARP等は必要ない。
### 課題z4-2-4: Multipath Routing
Multipath Routingは複数の経路でRoutingを行う。
バランシングを行うことで経路の帯域を余らせることなく有効活用できる。
Weightによって割合を決めることで柔軟に調整することができる。
下の設定を入れパケットキャプチャを行い、バランシングされていることを確認した。
しかし、宛先IPを変更するとバランシングされるが同じだと偏ってしまう。
これはRouting Cacheの影響?またはIPアドレスからハッシュ値を出している?
などと考えられる。Kernelによって異なるらしい...?
```
ip route add default \
nexthop via 10.1.0.1 dev eth0 weight 1 \
nexthop via 10.2.0.1 dev eth0 weight 1
```
## 課題z4-3(演習課題): Virtual Network Playground 1
下にまとめた通りのコマンドを入力する。
NameSpaceを分け、仮想ネットワークを作成する。
そのNameSpace内でコマンドを実行することでIPやSocketをNameSpace毎に独立させられる。
課題の構成図のインターフェース名は視認性を上げるために`<src>-<dst>`に変更して構築。
**環境**
- CentOS 7.9.2009(Proxmox VM)
```
// nsの追加
[root@dev]# ip netns add C1
[root@dev]# ip netns add C2
[root@dev]# ip netns add C3
[root@dev]# ip netns add C4
[root@dev]# ip netns add R1
[root@dev]# ip netns add R2
[root@dev]# ip netns ls
R2
R1
C4
C3
C2
C1
// vethインターフェースの作成
[root@dev]# ip link add C1-R1 type veth peer name R1-C1
[root@dev]# ip link add C2-R1 type veth peer name R1-C2
[root@dev]# ip link add R1-R2 type veth peer name R2-R1
[root@dev]# ip link add C3-R2 type veth peer name R2-C3
[root@dev]# ip link add C4-R2 type veth peer name R2-C4
[root@dev]# ip a | grep -E "^[0-9]"
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
3: R1-C1@C1-R1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000
4: C1-R1@R1-C1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000
5: R1-C2@C2-R1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000
6: C2-R1@R1-C2: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000
7: R2-R1@R1-R2: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000
8: R1-R2@R2-R1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000
9: R2-C3@C3-R2: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000
10: C3-R2@R2-C3: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000
11: R2-C4@C4-R2: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000
12: C4-R2@R2-C4: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000
// 各nsにインターフェースを割り当て
[root@dev]# ip link set R1-C1 netns R1 up
[root@dev]# ip link set R1-C2 netns R1 up
[root@dev]# ip link set R1-R2 netns R1 up
[root@dev]# ip link set R2-C3 netns R2 up
[root@dev]# ip link set R2-C4 netns R2 up
[root@dev]# ip link set R2-R1 netns R2 up
[root@dev]# ip link set C1-R1 netns C1 up
[root@dev]# ip link set C2-R1 netns C2 up
[root@dev]# ip link set C3-R2 netns C3 up
[root@dev]# ip link set C4-R2 netns C4 up
[root@dev]# ip a | grep -E "^[0-9]"
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
// Loopbackの有効化
[root@dev]# ip netns exec C1 ifup lo
[root@dev]# ip netns exec C2 ifup lo
[root@dev]# ip netns exec C3 ifup lo
[root@dev]# ip netns exec C4 ifup lo
[root@dev]# ip netns exec R1 ifup lo
[root@dev]# ip netns exec R2 ifup lo
// 各nsにIPアドレスを設定
[root@dev]# ip netns exec C1 ip addr add 10.1.0.2/24 dev C1-R1
[root@dev]# ip netns exec C2 ip addr add 10.2.0.2/24 dev C2-R1
[root@dev]# ip netns exec C3 ip addr add 10.3.0.2/24 dev C3-R2
[root@dev]# ip netns exec C4 ip addr add 10.4.0.2/24 dev C4-R2
[root@dev]# ip netns exec R1 ip addr add 10.1.0.1/24 dev R1-C1
[root@dev]# ip netns exec R1 ip addr add 10.2.0.1/24 dev R1-C2
[root@dev]# ip netns exec R1 ip addr add 10.255.1.1/24 dev R1-R2
[root@dev]# ip netns exec R2 ip addr add 10.3.0.1/24 dev R2-C3
[root@dev]# ip netns exec R2 ip addr add 10.4.0.1/24 dev R2-C4
[root@dev]# ip netns exec R2 ip addr add 10.255.1.2/24 dev R2-R1
[root@dev]# ip netns exec R1 ip addr add 1.1.1.1/32 dev lo label lo:2
[root@dev]# ip netns exec R2 ip addr add 2.2.2.2/32 dev lo label lo:2
// Default Routeの設定
[root@dev]# ip netns exec C1 ip route add default via 10.1.0.1
[root@dev]# ip netns exec C2 ip route add default via 10.2.0.1
[root@dev]# ip netns exec C3 ip route add default via 10.3.0.1
[root@dev]# ip netns exec C4 ip route add default via 10.4.0.1
[root@dev]# ip netns exec R1 ip route add default via 10.255.1.2
[root@dev]# ip netns exec R2 ip route add default via 10.255.1.1
// Routingを有効化
[root@dev]# ip netns exec R1 sysctl -w net.ipv4.ip_forward=1
[root@dev]# ip netns exec R2 sysctl -w net.ipv4.ip_forward=1
// 確認
[root@dev]# ip netns exec C1 ping 10.3.0.2
PING 10.3.0.2 (10.3.0.2) 56(84) bytes of data.
64 bytes from 10.3.0.2: icmp_seq=1 ttl=62 time=0.077 ms
64 bytes from 10.3.0.2: icmp_seq=2 ttl=62 time=0.071 ms
64 bytes from 10.3.0.2: icmp_seq=3 ttl=62 time=0.082 ms
```
## 課題z4-4(演習課題): Virtual Network Playground 2
下のコマンドの通り。
課題の中にC1<->C3間の通信でR1にてロードバランシングする指示はないため、
R3に接続できれば良いと判断した上での設定。
```
//新しくR3 NameSpaceを追加
[root@dev]# ip netns add R3
//インターフェース作成
[root@dev izumin]# ip link add R3-R1 type veth peer name R1-R3
[root@dev izumin]# ip link add R3-R2 type veth peer name R2-R3
// インターフェースの割当
[root@dev izumin]# ip link set R3-R1 netns R3 up
[root@dev izumin]# ip link set R3-R2 netns R3 up
[root@dev izumin]# ip link set R1-R3 netns R1 up
[root@dev izumin]# ip link set R2-R3 netns R2 up
// loopbackの有効化
[root@dev izumin]# ip netns exec R3 ifup lo
// IPアドレスの割当
[root@dev izumin]# ip netns exec R3 ip addr add 10.255.2.2/24 dev R3-R1
[root@dev izumin]# ip netns exec R3 ip addr add 10.255.3.2/24 dev R3-R2
[root@dev izumin]# ip netns exec R3 ip addr add 3.3.3.3/32 dev lo label lo:2
[root@dev izumin]# ip netns exec R1 ip addr add 10.255.2.1/24 dev R1-R3
[root@dev izumin]# ip netns exec R2 ip addr add 10.255.3.1/24 dev R2-R3
// Routingの有効化
[root@dev izumin]# ip netns exec R3 sysctl -w net.ipv4.ip_forward=1
// Static Routeの設定
[root@dev izumin]# ip netns exec R1 ip route add 3.3.3.3/32 via 10.255.2.2
[root@dev izumin]# ip netns exec R2 ip route add 3.3.3.3/32 via 10.255.3.2
[root@dev izumin]# ip netns exec R3 ip route add 10.1.0.0/24 via 10.255.2.1
[root@dev izumin]# ip netns exec R3 ip route add 10.2.0.0/24 via 10.255.2.1
[root@dev izumin]# ip netns exec R3 ip route add 1.1.1.1/32 via 10.255.2.1
[root@dev izumin]# ip netns exec R3 ip route add 10.3.0.0/24 via 10.255.3.1
[root@dev izumin]# ip netns exec R3 ip route add 10.4.0.0/24 via 10.255.3.1
[root@dev izumin]# ip netns exec R3 ip route add 2.2.2.2/32 via 10.255.3.1
[root@dev izumin]# ip netns exec R3 ip route add 10.255.1.0/24 via 10.255.3.1
// 確認
[root@dev izumin]# ip netns exec C1 ping 3.3.3.3
PING 3.3.3.3 (3.3.3.3) 56(84) bytes of data.
64 bytes from 3.3.3.3: icmp_seq=1 ttl=63 time=0.089 ms
64 bytes from 3.3.3.3: icmp_seq=2 ttl=63 time=0.063 ms
[root@dev izumin]# ip netns exec C3 ping 3.3.3.3
PING 3.3.3.3 (3.3.3.3) 56(84) bytes of data.
64 bytes from 3.3.3.3: icmp_seq=1 ttl=63 time=0.075 ms
64 bytes from 3.3.3.3: icmp_seq=2 ttl=63 time=0.061 ms
```
## 課題z4-5(演習課題): Virtual Network Playground 3
問題文の指定から、最小のホップ数であること、Dynamic Routingは余裕があったら行うという指定があるため、すべてStatic Routeで設定する。
FRRoutingについては今月中に時間が取れないので来月以降に試してみたいと思います。
```
// R1-R2の削除
ip netns exec R1 ip link delete R1-R2
// R1<->R3, R2<->R3のIPアドレスを変更
ip netns exec R1 ip addr del 10.255.2.1/24 dev R1-R3
ip netns exec R2 ip addr del 10.255.3.1/24 dev R2-R3
ip netns exec R3 ip addr del 10.255.2.2/24 dev R3-R1
ip netns exec R3 ip addr del 10.255.3.2/24 dev R3-R2
ip netns exec R1 ip addr add 10.255.1.1/24 dev R1-R3
ip netns exec R2 ip addr add 10.255.2.2/24 dev R2-R3
ip netns exec R3 ip addr add 10.255.1.3/24 dev R3-R1
ip netns exec R3 ip addr add 10.255.2.3/24 dev R3-R2
// R4とR5の追加
ip netns add R4
ip netns add R5
// インターフェースの作成
ip link add R1-R4 type veth peer name R4-R1
ip link add R4-R5 type veth peer name R5-R4
ip link add R5-R2 type veth peer name R2-R5
// インターフェースの割当
ip link set R1-R4 netns R1 up
ip link set R4-R1 netns R4 up
ip link set R4-R5 netns R4 up
ip link set R5-R4 netns R5 up
ip link set R5-R2 netns R5 up
ip link set R2-R5 netns R2 up
// loopbackの有効化
ip netns exec R4 ifup lo
ip netns exec R5 ifup lo
// IPアドレスの割当
ip netns exec R1 ip addr add 10.255.3.1/24 dev R1-R4
ip netns exec R4 ip addr add 10.255.3.4/24 dev R4-R1
ip netns exec R4 ip addr add 10.255.4.4/24 dev R4-R5
ip netns exec R4 ip addr add 4.4.4.4/32 dev lo label lo:2
ip netns exec R5 ip addr add 10.255.4.5/24 dev R5-R4
ip netns exec R5 ip addr add 10.255.5.5/24 dev R5-R2
ip netns exec R4 ip addr add 5.5.5.5/32 dev lo label lo:2
ip netns exec R2 ip addr add 10.255.5.2/24 dev R2-R5
// Routingの有効化
ip netns exec R4 sysctl -w net.ipv4.ip_forward=1
ip netns exec R5 sysctl -w net.ipv4.ip_forward=1
// Static Routeの設定
ip netns exec R1 ip route add default via 10.255.1.3
ip netns exec R1 ip route add 10.255.4.0/24 via 10.255.3.4
ip netns exec R1 ip route add 4.4.4.4/32 via 10.255.3.4
ip netns exec R1 ip route add 5.5.5.5/32 via 10.255.3.4
ip netns exec R2 ip route add default via 10.255.2.3
ip netns exec R2 ip route add 10.255.4.0/24 via 10.255.5.5
ip netns exec R2 ip route add 4.4.4.4/32 via 10.255.5.5
ip netns exec R2 ip route add 5.5.5.5/32 via 10.255.5.5
ip netns exec R3 ip route add 10.255.4.0/24 via 10.255.1.1
ip netns exec R3 ip route add 10.255.5.0/24 via 10.255.2.2
ip netns exec R3 ip route add 10.255.3.0/24 via 10.255.1.1
ip netns exec R3 ip route add 10.1.0.0/24 via 10.255.1.1
ip netns exec R3 ip route add 10.2.0.0/24 via 10.255.1.1
ip netns exec R3 ip route add 10.3.0.0/24 via 10.255.2.2
ip netns exec R3 ip route add 10.4.0.0/24 via 10.255.2.2
ip netns exec R3 ip route add 1.1.1.1/32 via 10.255.1.1
ip netns exec R3 ip route add 2.2.2.2/32 via 10.255.2.2
ip netns exec R3 ip route add 4.4.4.4/32 via 10.255.1.1
ip netns exec R3 ip route add 5.5.5.5/32 via 10.255.2.2
ip netns exec R4 ip route add default via 10.255.4.5
ip netns exec R4 ip route add 1.1.1.1/32 via 10.255.3.1
ip netns exec R4 ip route add 3.3.3.3/32 via 10.255.3.1
ip netns exec R4 ip route add 10.1.0.0/24 via 10.255.3.1
ip netns exec R4 ip route add 10.2.0.0/24 via 10.255.3.1
ip netns exec R4 ip route add 10.255.1.0/24 via 10.255.3.1
ip netns exec R5 ip route add default via 10.255.4.4
ip netns exec R5 ip route add 2.2.2.2/32 via 10.255.5.2
ip netns exec R5 ip route add 3.3.3.3/32 via 10.255.5.2
ip netns exec R5 ip route add 10.3.0.0/24 via 10.255.5.2
ip netns exec R5 ip route add 10.4.0.0/24 via 10.255.5.2
ip netns exec R5 ip route add 10.255.2.0/24 via 10.255.5.2
```
---
※2021/05/15追加
## FRRouting
実際に試してみました。
環境
- Ubuntu
- FRRouting version 7.5.1
**netnsによる環境設定**
```
// ns追加
ip netns add C1
ip netns add C2
ip netns add C3
ip netns add C4
ip netns add R1
ip netns add R2
ip netns add R3
ip netns add R4
ip netns add R5
//vethの追加
ip link add C1-R1 type veth peer name R1-C1
ip link add C2-R1 type veth peer name R1-C2
ip link add C3-R2 type veth peer name R2-C3
ip link add C4-R2 type veth peer name R2-C4
ip link add R1-R3 type veth peer name R3-R1
ip link add R1-R4 type veth peer name R4-R1
ip link add R4-R5 type veth peer name R5-R4
ip link add R2-R5 type veth peer name R5-R2
ip link add R2-R3 type veth peer name R3-R2
//interface設置
ip link set C1-R1 netns C1 up
ip link set C2-R1 netns C2 up
ip link set C3-R2 netns C3 up
ip link set C4-R2 netns C4 up
ip link set R1-C1 netns R1 up
ip link set R1-C2 netns R1 up
ip link set R1-R3 netns R1 up
ip link set R1-R4 netns R1 up
ip link set R2-C3 netns R2 up
ip link set R2-C4 netns R2 up
ip link set R2-R3 netns R2 up
ip link set R2-R5 netns R2 up
ip link set R3-R1 netns R3 up
ip link set R3-R2 netns R3 up
ip link set R4-R1 netns R4 up
ip link set R4-R5 netns R4 up
ip link set R5-R4 netns R5 up
ip link set R5-R2 netns R5 up
// Routingの有効化
ip netns exec R1 sysctl -w net.ipv4.ip_forward=1
ip netns exec R2 sysctl -w net.ipv4.ip_forward=1
ip netns exec R3 sysctl -w net.ipv4.ip_forward=1
ip netns exec R4 sysctl -w net.ipv4.ip_forward=1
ip netns exec R5 sysctl -w net.ipv4.ip_forward=1
// IPアドレス設定
ip netns exec C1 ip addr add 10.1.0.2/24 dev C1-R1
ip netns exec C2 ip addr add 10.2.0.2/24 dev C2-R1
ip netns exec C3 ip addr add 10.3.0.2/24 dev C3-R2
ip netns exec C4 ip addr add 10.4.0.2/24 dev C4-R2
ip netns exec R1 ip addr add 10.1.0.1/24 dev R1-C1
ip netns exec R1 ip addr add 10.2.0.1/24 dev R1-C2
ip netns exec R1 ip addr add 10.255.1.1/24 dev R1-R3
ip netns exec R1 ip addr add 10.255.3.1/24 dev R1-R4
ip netns exec R1 ip addr add 1.1.1.1/32 dev lo label lo:2
ip netns exec R2 ip addr add 10.3.0.1/24 dev R2-C3
ip netns exec R2 ip addr add 10.4.0.1/24 dev R2-C4
ip netns exec R2 ip addr add 10.255.2.2/24 dev R2-R3
ip netns exec R2 ip addr add 10.255.5.2/24 dev R2-R5
ip netns exec R2 ip addr add 2.2.2.2/32 dev lo label lo:2
ip netns exec R3 ip addr add 10.255.1.3/24 dev R3-R1
ip netns exec R3 ip addr add 10.255.2.3/24 dev R3-R2
ip netns exec R3 ip addr add 3.3.3.3/32 dev lo label lo:2
ip netns exec R4 ip addr add 10.255.3.4/24 dev R4-R1
ip netns exec R4 ip addr add 10.255.4.4/24 dev R4-R5
ip netns exec R4 ip addr add 4.4.4.4/32 dev lo label lo:2
ip netns exec R5 ip addr add 10.255.4.5/24 dev R5-R4
ip netns exec R5 ip addr add 10.255.5.5/24 dev R5-R2
ip netns exec R5 ip addr add 5.5.5.5/32 dev lo label lo:2
//CXのスタティック設定
ip netns exec C1 ip route add 0.0.0.0/0 via 10.1.0.1
ip netns exec C2 ip route add 0.0.0.0/0 via 10.2.0.1
ip netns exec C3 ip route add 0.0.0.0/0 via 10.3.0.1
ip netns exec C4 ip route add 0.0.0.0/0 via 10.4.0.1
```
**FRRのインストール**
Debianではレポジトリがあるため, 公式のとおりにそのままインストール
```
# curl -s https://deb.frrouting.org/frr/keys.asc | sudo apt-key add -
# FRRVER="frr-stable"
# echo deb https://deb.frrouting.org/frr $(lsb_release -s -c) $FRRVER | sudo tee -a /etc/apt/sources.list.d/frr.list
# sudo apt update && sudo apt install frr frr-pythontools
```
**Daemon構成**
デーモンはOSPFとBGPを有効化する。
`/etc/frr/daemons`を確認。利用するプロトコルを選択する。
```
+ bgpd=yes
- bgpd=no
+ ospfd=yes
- ospfd=no
ospf6d=no
ripd=no
~省略~
```
**Namespaceを利用**
netnsを利用するため、FRRの構成パススーペースを変更する。
`/etc/frr/<NameSpace>` にファイルを作成すると同時に、daemonsファイルを書き換える。
```
# vim /etc/frr/daemons
- #watchfrr_options="--netns"
+ watchfrr_options="--netns"
# cp /etc/frr/daemons /etc/frr/<NameSpace>/daemons
```
**Daemonを起動する**
NameSpaceを利用する場合は起動方法が特殊。
`ip netns exec <NameSpace> /etc/init.d/frr start <NameSpace>`
しかし、このようなコマンドを入力しても以下のようなエラーが発生する
```
root@dev2:/etc/frr# ip netns exec R1 /etc/init.d/frr start R1
Starting frr (via systemctl): frr.service.
```
ぐぐるとこんな解決方法を発見
`https://qiita.com/calcabrina/items/d0cae378e7b2d49f6ae6`
この記事を参考にコマンドを実施
```
SYSTEMCTL_SKIP_REDIRECT=1 ip netns exec R1 /etc/init.d/frr start R1
SYSTEMCTL_SKIP_REDIRECT=1 ip netns exec R2 /etc/init.d/frr start R2
SYSTEMCTL_SKIP_REDIRECT=1 ip netns exec R3 /etc/init.d/frr start R3
SYSTEMCTL_SKIP_REDIRECT=1 ip netns exec R4 /etc/init.d/frr start R4
SYSTEMCTL_SKIP_REDIRECT=1 ip netns exec R5 /etc/init.d/frr start R5
```
各nsはOSPFのプロセスを`127.0.0.1:2604`でLISTENする。
`/etc/services`に対応するポート番号は記載されている。
telnetでプロセスに入り、コンフィグを注入していく。
```
ip netns exec R1 telnet localhost 2604
en
conf t
hostname R1
router ospf
ospf router-id 1.1.1.1
passive-interface R1-C1
passive-interface R1-C2
network 10.255.1.0/24 area 0
network 10.255.3.0/24 area 0
int R1-R3
ip ospf network point-to-point
int R1-R4
ip ospf network point-to-point
==========
他のルータも同様にトポロジに合わせて設定
```
**!!注意点!!**
```
# router ospf 1
のようにプロセスIDを指定してしまうと、networkコマンドが動作しなかった。
"The network command is not supported in multi-instance ospf "
というエラーが発生する。
```
**設定の確認と動作確認**
```
//R1に入る
# vtysh -N R1
# show ip route
dev2# show ip route
Codes: K - kernel route, C - connected, S - static, R - RIP,
O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP,
F - PBR, f - OpenFabric,
> - selected route, * - FIB route, q - queued, r - rejected, b - backup
O 1.1.1.1/32 [110/0] is directly connected, lo, weight 1, 00:48:26
C>* 1.1.1.1/32 is directly connected, lo, 01:08:11
O>* 2.2.2.2/32 [110/20] via 10.255.1.3, R1-R3, weight 1, 00:03:58
O>* 3.3.3.3/32 [110/10] via 10.255.1.3, R1-R3, weight 1, 00:00:42
O>* 4.4.4.4/32 [110/10] via 10.255.3.4, R1-R4, weight 1, 00:01:06
O>* 5.5.5.5/32 [110/20] via 10.255.3.4, R1-R4, weight 1, 00:01:57
O 10.1.0.0/24 [110/10] is directly connected, R1-C1, weight 1, 00:06:30
C>* 10.1.0.0/24 is directly connected, R1-C1, 01:08:11
O 10.2.0.0/24 [110/10] is directly connected, R1-C2, weight 1, 00:06:28
C>* 10.2.0.0/24 is directly connected, R1-C2, 01:08:11
O>* 10.3.0.0/24 [110/30] via 10.255.1.3, R1-R3, weight 1, 00:03:58
O>* 10.4.0.0/24 [110/30] via 10.255.1.3, R1-R3, weight 1, 00:03:58
O 10.255.1.0/24 [110/10] is directly connected, R1-R3, weight 1, 00:05:58
C>* 10.255.1.0/24 is directly connected, R1-R3, 01:08:11
O>* 10.255.2.0/24 [110/20] via 10.255.1.3, R1-R3, weight 1, 00:03:58
O 10.255.3.0/24 [110/10] is directly connected, R1-R4, weight 1, 00:05:56
C>* 10.255.3.0/24 is directly connected, R1-R4, 01:08:11
O>* 10.255.4.0/24 [110/20] via 10.255.3.4, R1-R4, weight 1, 00:02:58
O>* 10.255.5.0/24 [110/30] via 10.255.1.3, R1-R3, weight 1, 00:01:06
* via 10.255.3.4, R1-R4, weight 1, 00:01:06
//R1のnsからの疎通
# ip netns exec R1 bash
# ip route show
2.2.2.2 nhid 38 via 10.255.1.3 dev R1-R3 proto ospf metric 20
3.3.3.3 nhid 38 via 10.255.1.3 dev R1-R3 proto ospf metric 20
4.4.4.4 nhid 40 via 10.255.3.4 dev R1-R4 proto ospf metric 20
5.5.5.5 nhid 40 via 10.255.3.4 dev R1-R4 proto ospf metric 20
10.1.0.0/24 dev R1-C1 proto kernel scope link src 10.1.0.1
10.2.0.0/24 dev R1-C2 proto kernel scope link src 10.2.0.1
10.3.0.0/24 nhid 38 via 10.255.1.3 dev R1-R3 proto ospf metric 20
10.4.0.0/24 nhid 38 via 10.255.1.3 dev R1-R3 proto ospf metric 20
10.255.1.0/24 dev R1-R3 proto kernel scope link src 10.255.1.1
10.255.2.0/24 nhid 38 via 10.255.1.3 dev R1-R3 proto ospf metric 20
10.255.3.0/24 dev R1-R4 proto kernel scope link src 10.255.3.1
10.255.4.0/24 nhid 40 via 10.255.3.4 dev R1-R4 proto ospf metric 20
10.255.5.0/24 nhid 44 proto ospf metric 20
nexthop via 10.255.1.3 dev R1-R3 weight 1
nexthop via 10.255.3.4 dev R1-R4 weight 1
root@dev2:/etc/frr# ping 10.4.0.2
PING 10.4.0.2 (10.4.0.2) 56(84) バイトのデータ
64 バイト応答 送信元 10.4.0.2: icmp_seq=1 ttl=62 時間=0.084ミリ秒
64 バイト応答 送信元 10.4.0.2: icmp_seq=2 ttl=62 時間=0.055ミリ秒
64 バイト応答 送信元 10.4.0.2: icmp_seq=3 ttl=62 時間=0.055ミリ秒
64 バイト応答 送信元 10.4.0.2: icmp_seq=4 ttl=62 時間=0.055ミリ秒
^C
--- 10.4.0.2 ping 統計 ---
送信パケット数 4, 受信パケット数 4, パケット損失 0%, 時間 3064ミリ秒
rtt 最小/平均/最大/mdev = 0.055/0.062/0.084/0.012ミリ秒
```
OSPFはnetns+FRRで動作することを確認しました。
BGPについては今は知識不足なので保留します。講座までに少しずつ学ぼうと思います。
ソフトウェアRoutingは初めて触るのでOSPFとzebraとプロセスが分離している点など頭がうまく整理できていません。
一度レクチャー等聞ければ大変勉強になるかと思います…
以上。よろしくお願いいたします。
```