LinuxでPBR

AWSでインスタンスを立ち上げたとき,2つのサブネットに所属させ一方は社内ネットワーク,一方はメンテナンス用に外部(インターネット)からSSHアクセス用にと構成することがある。

この場合,それぞれのNICに着信したトラフィックはそのNICから応答を返して欲しいが通信元が不特定だとスタティックルートで処理するのは不可能。このような時はPBRを設定して対応する。
参考) 

手順

  • ルートテーブルの作成
  • ポリシーの作成
  • ルーティングの追加
  • 永続的設定

ルートテーブルの作成

/etc/iproute2/rt_tables にens192用のルーティングテーブル「rt10」とens224用のルーティングテーブル「rt100」を追加する。なお,IDは1~255まであり,254はmainテーブル,255はlocalでリザーブされている。ここでは100と101を使用する。
#
# reserved values
#
255 local
254 main
253 default
0 unspec
#
# local
#
#1 inr.ruhep
100 rt100 #追加
101 rt10 #追加

ポリシーの作成

書式: ip rule add from <IF address> table <table name> priority <priority number>
# ip rule add from 192.168.10.40 table rt10 priority 100
# ip rule add from 192.168.1.40 table rt100 priority 101

prioritを指定しないとカーネルが一番古いpriorityの前に自動で採番する。何も設定されていなければmainの32766の前に順に追加される。(32765,32764という感じで)

ルーティングの追加

書式: ip route add default via <Gateway address> dev <IF name> table <table name> 
# ip route add default via 192.168.10.1 dev ens192 table rt10
# ip route add default via 192.168.1.1 dev ens224 table rt100
まずはこれでPBRは設定完了。
192.168.1.0/24にいるPCからpingのテスト。
PBR設定前はens192からreplyが返っていない。(なお,リバースパスフィルタリングが有効になっているのでens224では戻りのパケットがかえらない)
PBR設定後はしっかり着信IFからreplyが返っている。

永続的設定

コマンドで設定したルールとルートは再起動で消えるため,/etc/sysconfig/network-script配下に定義ファイルを作成するとあったが,NetworkMangerを利用している環境では利用できない。

・ ルール定義

/etc/sysconfig/network-script/rule-<IF名>
各IFに先のコマンドを記述。
ip rule add from 192.168.10.40 table rt10 priority 100
ip rule add from 192.168.1.40 table rt100 priority 101

・ ルート定義

/etc/sysconfig/network-script/route-<IF名>
各IFに先のコマンドを記述。
ip route add default via 192.168.10.1 dev ens192 table rt10
ip route add default via 192.168.1.1 dev ens224 table rt100
これがNGとなると,起動スクリプトに上のコマンドを実行するように仕込む方法が考えられる。
pbr.sh
#!/bin/sh
## create rules for pbr

ip rule add from 192.168.10.40 table rt10 priority 100
ip rule add from 192.168.1.40 table rt100 priority 101

## create default route for each routing tables
ip route add default via 192.168.10.1 dev ens192 table rt10
ip route add default via 192.168.1.1 dev ens224 table rt100
/etc/systemd/system/pbr.service
[Unit]
Description = PBR setting script
After = network-online.target # NICがオンラインにならないとコマンドが失敗に終わるため

[Service]
ExecStart = /root/pbr.sh
Type = simple

[Install]
WantedBy = multi-user.target

ここまで準備できたら
# systemctl enable pbr.service
# systemctl start pbr.service
で完了。
ただここまでやっておきながら,nmcliを使えばコマンド1行で終わることが分かった。

nmcliを使う方法

ens192の設定
nmcli con add type ethernet con-name ens192 ifname ens192 ipv4.method manual ipv4.addresses 192.168.10.40/24 ipv4.routes "0.0.0.0/1 192.168.10.1 table=100, 128.0.0.0/1 192.168.10.1 table=100" ipv4.routing-rules "priority 100 from 192.168.10.40 table 100"
ens224の設定
nmcli con add type ethernet con-name ens224 ifname ens224 ipv4.method manual ipv4.addresses 192.168.1.40/24 ipv4.routes "0.0.0.0/1 192.168.1.1 table=101, 128.0.0.0/1 192.168.1.1 table=101" ipv4.routing-rules "priority 101 from 192.168.1.40 table 101"
以上。超簡単。再起動後もこれで対応している。
RHELの公式ドキュメントによると,nmcliは0.0.0.0/0の表記に対応していないとのことで,0.0.0.0/1と128.0.0.0/1の2つ定義を入れて0.0.0.0/0をカバーしなくてはならないとのこと。この点とテーブルを名前指定ができず番号で記述する必要があるのがややわかりにくい。
ちなみにIFの設定ファイルは以下にある。
/etc/NetworkManager/system-connections/ens192.nmconnection 
/etc/NetworkManager/system-connections/ens224.nmconnection 

MikroTik CRS309を手に入れた

欲しかった10Gのスイッチを米アマ経由で調達した。
環境準備や設定・スループット測定などいろいろと手間取ったのでメモ。
購入したのMikroTik CRS309。米アマで購入当時およそ$270。輸送費やもろもろ税がかかって日本円で3.3万円程度で本体を手に入れた。
こちらは日本アマゾン

ざっと所感

– それなりにお金がかかる

・10GのSFPが必要なので,本体以外にもケーブル/デバイス側の10G NICといった費用も考えて調達しないとキツイ。なお,SFP+は(こちらも米アマで購入)SFP+とDACで大体4万円くらいかかった。
1なので,トータルで7.3万円で10GのL3SWを手に入れたことになる。

– 仕様はよくチェックしよう

公式のガイドラインで「10Gbase-TのときはRJ45モジュールが熱くなるから1ポート間隔あけて搭載することが推奨」あった。想定外だった。確かに触っていると火傷するほどアッツイ。よく調べよう。(以下,ガイドライン抜粋)
Even when using devices that come with separated SFP+ cages, for example CRS309-1G-8S+, it is still not recommended to deploy the S+RJ10 transceivers beside each other. Use S+RJ10 in every second interface to avoid transceivers overheating which may cause unpredictable behavior.

– CLIが独特

show run のような現状のConfigを確認するコマンドが無いので,CLIとWebUIを組み合わせて操作することになると思う。

– 設定も独特

bridgeやらswitchやらinterfaceやらと設定のセクション分けが困惑する。丸1日2日触っているとだいぶ慣れてくるけど,IOSやJunosのような感覚でいると訳分からなくなる。

スループット測定

– snake test

snake test
snake test イメージ
10Gに対応しているPCを2台準備できなかったので,CentOS8にDual portの10Gを積んで,network namespaceで分離しiperf3で測定した。

– 測定準備

予めNIC側のMTUを9000に設定する。
nmcli connection show でデバイスのUUIDを確認。
9000へ変更。
nmcli con mod UUID1 802-3.mtu 9000
nmcli con mod UUID2 802-3.mtu 9000
systemctl restart NetworkManager
Namespace作成
sudo ip netns add NIC1
sudo ip netns add NIC2
そえぞれのNICをNamespaceへ割り当てる。
sudo ip link set enp1s0f0 netns NIC1 up
sudo ip link set enp1s0f1 netns NIC2 up
IP設定
sudo ip netns exec NIC1 bash
ip addr add 10.10.10.1/30 dev enp1s0f0
sudo ip netns exec NIC2 bash
ip addr add 10.10.10.2/30 dev enp1s0f1
CSR309のL2MTUはMAXで10218。
interface set l2mtu=10218 1

テスト結果

およそ10Gbpsでました。
実環境ではここまでではないだろうけれど,パーソナルユースなので細かいところまではテストしない。
なお,公式でスループットのテスト結果が公開されているのでこれで十分だと思う。
この後はCisco891Mとのリプレースをやる。

Cisco IOSで設定のロールバック

先日のメモではIOSでのアーカイブについて触れたけど,今回は安全にロールバックを行う方法ついて確認。

そもそもCisco IOSでの設定即時反映は便利である反面,ミスったときの影響が大きいという問題があると感じていた。その点,JunosやVyOSのようなその他のNW OSで実装されている,設定反映前の比較やロールバックタイマーは運用を担っている人達からすると非常に助かる機能だと思う。
IOSはどうしてこの機能を盛り込まないのだろうと思っていたけれど,結構前からそれに類するコマンドはあったようで,私は知りませんでした。(12.2位からあったようで・・・)
<configure replace コマンド>
設定をロールバックするときはこのコマンドを使う。
こちらによると,稼働中のConfigとの差分のみを適用してくれるとのことで,copy xxx running-conifg のようにまるっと上書きよりも安全に変更できるそうだ。(コマンドリファレンスには置き換えるとしか書いていないけど,そうなのか)

試しにホスト名を変えてロールバックをしてみる。

R1#conf t
Enter configuration commands, one per line. End with CNTL/Z.
R1(config)#hostname Router1
Router1(config)#end
Router1#show archive
The maximum archive configurations allowed is 10.
The next archive file will be named ftp://10.10.10.10/Router1--3605
Archive # Name
1 ftp://10.10.10.10/R1-May--8-01-53-04.568-3595
2 ftp://10.10.10.10/R1-May--8-01-56-04.701-3596
3 ftp://10.10.10.10/R1-May--8-01-59-04.848-3597
4 ftp://10.10.10.10/R1-May--8-02-02-04.993-3598
5 ftp://10.10.10.10/R1-May--8-02-05-05.127-3599
6 ftp://10.10.10.10/R1-May--8-02-08-05.277-3600
7 ftp://10.10.10.10/R1-May--8-02-11-05.411-3601
8 ftp://10.10.10.10/R1-May--8-02-14-05.568-3602
9 ftp://10.10.10.10/R1-May--8-02-17-06.489-3603
10 ftp://10.10.10.10/R1-May--8-02-20-07.340-3604 <- Most Recent

ホスト名がR1からRouter1へ変わったので一つ前のArchive9へロールバックする。

Router1#configure replace ftp://10.10.10.10/R1-May--8-02-17-06.489-3603
This will apply all necessary additions and deletions
to replace the current running configuration with the
contents of the specified configuration file, which is
assumed to be a complete configuration, not a partial
configuration. Enter Y if you are sure you want to proceed. ? [no]: yes # 確認で「yes」と入力
Loading R1-May--8-02-17-06.489-3603 !
[OK - 1105/4096 bytes]

Loading R1-May--8-02-17-06.489-3603 !
[OK - 1105/4096 bytes]

Total number of passes: 1
Rollback Done

R1#

R1へ戻った。戻したい状態が明確なので,hostname R1 と設定を変更するよりも安全に戻せる。
ただし,これは即時反映のため,一定時間で元に戻したい場合は,さらにオプションで「 trigger timer <1-120(min)> 」をつけて何分後に元に戻すかを指定する。
これで,「うわぁ!ロールバック元間違えた!」という時にも安心していられる(?)。

trigger timer オプションをつけて実行し,問題なければ,「configure confirm」で確定してロールバック完了となる。

以下は,ロールバック実行/1分後にロールバック自体を元に戻す流れ。

Switch1#configure replace ftp://10.10.10.10/R1-May--8-02-47-14.947-3616 revert trigger timer 1    # 1分後にロールバックを元にもどす
Writing Switch1-May--8-02-47-53.701-3618 Rollback Confirmed Change: Backing up current running config to ftp://10.10.10.10/Switch1-May--8-02-47-53.701-3618

This will apply all necessary additions and deletions
to replace the current running configuration with the
contents of the specified configuration file, which is
assumed to be a complete configuration, not a partial
configuration. Enter Y if you are sure you want to proceed. ? [no]: yes
Loading R1-May--8-02-47-14.947-3616 !
[OK - 1105/4096 bytes]

*May 8 02:47:53.814: %ARCHIVE_DIFF-5-ROLLBK_CNFMD_CHG_BACKUP: Backing up current running config to ftp://10.10.10.10/Switch1-May--8-02-47-53.701-3618
Loading R1-May--8-02-47-14.947-3616 !
[OK - 1105/4096 bytes]

Total number of passes: 1
Rollback Done

R1#Rollback Confirmed Change: Rollback will begin in one minute. # ホスト名がR1に戻った。ロールバック完了。
Enter "configure confirm" if you wish to keep what you've configured
*May 8 02:47:55.655: Rollback:Acquired Configuration lock.
R1#
*May 8 02:47:55.771: %ARCHIVE_DIFF-5-ROLLBK_CNFMD_CHG_START_ABSTIMER: User: console(Priv: 15, View: 0): Scheduled to rollback to config ftp://10.10.10.10/Switch1-May--8-02-47-53.701-3618 in 1 minutes
*May 8 02:47:55.775: %ARCHIVE_DIFF-5-ROLLBK_CNFMD_CHG_WARNING_ABSTIMER: System will rollback to config ftp://10.10.10.10/Switch1-May--8-02-47-53.701-3618 in one minute. Enter "configure confirm" if you wish to keep what you've configured
R1#Rollback Confirmed Change: rolling to:ftp://10.10.10.10/Switch1-May--8-02-47-53.701-3618

Loading Switch1-May--8-02-47-53.701-3618 !
[OK - 1110/4096 bytes]

Loading Switch1-May--8-02-47-53.701-3618 !
[OK - 1110/4096 bytes]

!Pass 1
!List of Rollback Commands:
no hostname R1
hostname Switch1
end


Total number of passes: 1
Rollback Done

*May 8 02:48:55.776: %ARCHIVE_DIFF-5-ROLLBK_CNFMD_CHG_ROLLBACK_START: Start rolling to: ftp://10.10.10.10/Switch1-May--8-02-47-53.701-3618
*May 8 02:48:55.852: Rollback:Acquired Configuration lock.
R1#
Switch1# # 1分経過したためロールバックがもどされ,ホスト名が Switch1 に戻った。

ロールバックを確定する流れは以下のようになる。

Switch1#configure replace ftp://10.10.10.10/R1-May--8-02-47-14.947-3616 revert trigger timer 1
Writing Switch1-May--8-02-55-47.783-3621 Rollback Confirmed Change: Backing up current running config to ftp://10.10.10.10/Switch1-May--8-02-55-47.783-3621

This will apply all necessary additions and deletions
to replace the current running configuration with the
contents of the specified configuration file, which is
assumed to be a complete configuration, not a partial
configuration. Enter Y if you are sure you want to proceed. ? [no]: yes
Loading R1-May--8-02-47-14.947-3616 !
[OK - 1105/4096 bytes]

*May 8 02:55:47.855: %ARCHIVE_DIFF-5-ROLLBK_CNFMD_CHG_BACKUP: Backing up current running config to ftp://10.10.10.10/Switch1-May--8-02-55-47.783-3621
Loading R1-May--8-02-47-14.947-3616 !
[OK - 1105/4096 bytes]

Total number of passes: 1
Rollback Done

R1#Rollback Confirmed Change: Rollback will begin in one minute.
Enter "configure confirm" if you wish to keep what you've configured

*May 8 02:55:49.323: Rollback:Acquired Configuration lock.
R1#
R1#
*May 8 02:55:49.427: %ARCHIVE_DIFF-5-ROLLBK_CNFMD_CHG_START_ABSTIMER: User: console(Priv: 15, View: 0): Scheduled to rollback to config ftp://10.10.10.10/Switch1-May--8-02-55-47.783-3621 in 1 minutes
*May 8 02:55:49.431: %ARCHIVE_DIFF-5-ROLLBK_CNFMD_CHG_WARNING_ABSTIMER: System will rollback to config ftp://10.10.10.10/Switch1-May--8-02-55-47.783-3621 in one minute. Enter "configure confirm" if you wish to keep what you've configured
R1#
R1#configure confirm
R1#
*May 8 02:55:55.567: %ARCHIVE_DIFF-5-ROLLBK_CNFMD_CHG_CONFIRM: User: console: Confirm the configuration change
R1#

今後はこれを活用していきたい。

もう1点良いと思うところは,ロールバック手順で設定変更を行えば,Configの投入順序を気にしなくても良いという点。
例えばIPSecの設定で,transform-set を先に設定してからcrypto mapの中で定義しなくてはならないが,そういったところを意識しなくても良い。
流し込みミスと併せて,事前に流し込みの順序を考える必要がないというのは結構利点だと思う。
R1(config-crypto-map)#set transform-set TS
%ERROR: transform set with tag "TS" does not exist.

こういうことが防げる。

IOSの設定ファイルをFTPサーバへ保存して世代管理する。

Cisco IOSでConfigの世代管理をターミナルソフトでログ出力してローカル保存することから脱却したいと考え,AnsibleやNetconfなども考えたが今の現場では人力設定変更からの脱却がなかなかに難しい。(政治的にも運用的にもスキルセット的にも)

ということで,現行の環境をできるだけそのままに新しい機能では無いけど,「archive」コマンドで少しは幸せになれそうな気がしたので検証。

今回の検証環境はシンプルに,ルータ2台,FTPサーバ1台とする。

FTPサーバ(10.10.10.10)へConfigをアーカイブする

「archive」コマンドはマニュアルでも実行でき,設定しておけば自動で指定した場所へConfigを保存してくれる。デフォルトでは10世代まで保存となっており,maximumオプションで1~14まで指定ができる。

IOSのコンフィギュレーション アーカイブ

図のR1とR2に以下定義を入れる。

! FTPの基本設定
ip ftp source-interface Ethernet0/0
ip ftp username user
ip ftp password Test123

! アーカイブ設定
archive
path ftp://10.10.10.10/$h # $h は機器のホスト名
write-memory # 設定保存時にアーカイブ実行
time-period 3 # アーカイブを実行するタイミングの指定。今回は検証なので3分とした。

設定保存時と定期的にアーカイブをする設定を入れたが,time-periodはアーカイブをしたタイミングを起点に何分後という説明だったので,自動と手動のどちらも見るのか気になり確認をしたところ,archiveを設定した時点から定期的に取得するらしく,「archive config」コマンドで手動で実行したアーカイブは無視されていた。

R1#show archive
The maximum archive configurations allowed is 10.
The next archive file will be named ftp://10.10.10.10/R1--9
Archive # Name
1 ftp://10.10.10.10/R1-Apr-30-14-27-36.582-0
2 ftp://10.10.10.10/R1-Apr-30-14-28-49.035-1 # archiveコマンド設定後,最初の自動アーカイブ
3 ftp://10.10.10.10/R1-Apr-30-14-31-50.160-2 # 初回から3分後,2回目のアーカイブ
4 ftp://10.10.10.10/R1-Apr-30-14-34-51.091-3 # 3回目の自動アーカイブ
5 ftp://10.10.10.10/R1-Apr-30-14-34-59.006-4 # 「archive config」コマンドで手動でアーカイブを実行
6 ftp://10.10.10.10/R1-Apr-30-14-35-09.006-5 # 「archive config」コマンドで手動でアーカイブを実行
7 ftp://10.10.10.10/R1-Apr-30-14-37-52.197-6 # 4回目の自動アーカイブ
8 ftp://10.10.10.10/R1-Apr-30-14-39-17.723-7 # 「archive config」コマンドで手動でアーカイブを実行
9 ftp://10.10.10.10/R1-Apr-30-14-40-53.180-8 < -- Most Recent

この構成にすることでアーカイブと対となるロールバックも可能になる。

例えば,LAN側インタフェースの設定を入れたあと,誤って設定を消してしまった場合,「configure replace」コマンドでロールバックを行うことができる。

R1#show ip
*Apr 30 14:51:51.064: %LINK-3-UPDOWN: Interface Ethernet0/1, changed state to up
*Apr 30 14:51:52.072: %LINEPROTO-5-UPDOWN: Line protocol on Interface Ethernet0/1, changed state to up
R1#show ip int brie
Interface IP-Address OK? Method Status Protocol
Ethernet0/0 10.10.10.1 YES manual up up
Ethernet0/1 192.168.1.1 YES manual up up
Ethernet0/2 unassigned YES unset administratively down down
Ethernet0/3 unassigned YES unset administratively down down
R1#
R1#copy run startup-config
Destination filename [startup-config]?
Building configuration...
[OK]
Writing R1-Apr-30-14-51-57.355-12
R1#
R1#conf t
Enter configuration commands, one per line. End with CNTL/Z.
R1(config)#default interface e0/1 #やっちまった!!!
Interface Ethernet0/1 set to default configuration
R1(config)#do show ip int brie
Interface IP-Address OK? Method Status Protocol
Ethernet0/0 10.10.10.1 YES manual up up
Ethernet0/1 unassigned YES TFTP up up
Ethernet0/2 unassigned YES unset administratively down down
Ethernet0/3 unassigned YES unset administratively down down

手動で簡単に戻せるレベルだが,せっかくアーカイブをとっているので一つ前の設定へロールバックする。

R1#show archive
The maximum archive configurations allowed is 10.
The next archive file will be named ftp://10.10.10.10/R1-<timestamp>-15
Archive # Name
1 ftp://10.10.10.10/R1-Apr-30-14-35-09.006-5
2 ftp://10.10.10.10/R1-Apr-30-14-37-52.197-6
3 ftp://10.10.10.10/R1-Apr-30-14-39-17.723-7
4 ftp://10.10.10.10/R1-Apr-30-14-40-53.180-8
5 ftp://10.10.10.10/R1-Apr-30-14-43-54.061-9
6 ftp://10.10.10.10/R1-Apr-30-14-46-54.980-10
7 ftp://10.10.10.10/R1-Apr-30-14-49-56.023-11
8 ftp://10.10.10.10/R1-Apr-30-14-51-57.355-12
9 ftp://10.10.10.10/R1-Apr-30-14-52-56.856-13
10 ftp://10.10.10.10/R1-Apr-30-14-55-58.039-14 <- Most Recent

一つ前は「ftp://10.10.10.10/R1-Apr-30-14-52-56.856-13」なので,これを指定してロールバックを実行する。

R1#configure replace ftp://10.10.10.10/R1-Apr-30-14-52-56.856-13
This will apply all necessary additions and deletions
to replace the current running configuration with the
contents of the specified configuration file, which is
assumed to be a complete configuration, not a partial
configuration. Enter Y if you are sure you want to proceed. ? [no]: yes
Loading R1-Apr-30-14-52-56.856-13 !
[OK - 1106/4096 bytes]

Loading R1-Apr-30-14-52-56.856-13 !
[OK - 1106/4096 bytes]

Total number of passes: 1
Rollback Done

R1#
*Apr 30 15:00:31.984: Rollback:Acquired Configuration lock.
R1#show ip int brie
Interface IP-Address OK? Method Status Protocol
Ethernet0/0 10.10.10.1 YES manual up up
Ethernet0/1 192.168.1.1 YES TFTP up up
Ethernet0/2 unassigned YES unset administratively down down
Ethernet0/3 unassigned YES unset administratively down down
R1#show arc
R1#show archive
The maximum archive configurations allowed is 10.
The next archive file will be named ftp://10.10.10.10/R1-<timestamp>-16
Archive # Name
1 ftp://10.10.10.10/R1-Apr-30-14-37-52.197-6
2 ftp://10.10.10.10/R1-Apr-30-14-39-17.723-7
3 ftp://10.10.10.10/R1-Apr-30-14-40-53.180-8
4 ftp://10.10.10.10/R1-Apr-30-14-43-54.061-9
5 ftp://10.10.10.10/R1-Apr-30-14-46-54.980-10
6 ftp://10.10.10.10/R1-Apr-30-14-49-56.023-11
7 ftp://10.10.10.10/R1-Apr-30-14-51-57.355-12
8 ftp://10.10.10.10/R1-Apr-30-14-52-56.856-13
9 ftp://10.10.10.10/R1-Apr-30-14-55-58.039-14
10 ftp://10.10.10.10/R1-Apr-30-14-58-59.227-15 <- Most Recent
R1#

無事に設定はもどり,アーカイブ番号は戻るのではなく更新される。

いちいちどの定義を入れ直さなくてはダメなのか,という確認が不要なので便利だと思うし,運用に入った環境では人的ミスの削減にもつながるはず。
ちなみにアーカイブの差分も以下コマンドで確認できる。

R11#$R11-Apr-30-15-25-28.087-24 ftp://10.10.10.10/R1-Apr-30-15-23-03.315-23
Loading R11-Apr-30-15-25-28.087-24 !
[OK - 1106/4096 bytes]

Loading R1-Apr-30-15-23-03.315-23 !
[OK - 1105/4096 bytes]
!Contextual Config Diffs:
+hostname R1
-hostname R11

なお,FTPサーバ側にもちゃんとファイルが保存されている。

[user@localhost ~]$ ls -lrt
合計 128
-rw-r--r--. 1 user user 1093 4月 30 10:27 R1-Apr-30-14-27-36.582-0
-rw-r--r--. 1 user user 1073 4月 30 10:28 R2-Apr-30-14-28-22.973-1
-rw-r--r--. 1 user user 1093 4月 30 10:28 R1-Apr-30-14-28-49.035-1
-rw-r--r--. 1 user user 1073 4月 30 10:29 R2-Apr-30-14-29-06.901-2
-rw-r--r--. 1 user user 1093 4月 30 10:31 R1-Apr-30-14-31-50.160-2
-rw-r--r--. 1 user user 1073 4月 30 10:32 R2-Apr-30-14-32-08.023-3
-rw-r--r--. 1 user user 1093 4月 30 10:34 R1-Apr-30-14-34-51.091-3
-rw-r--r--. 1 user user 1093 4月 30 10:34 R1-Apr-30-14-34-59.006-4
-rw-r--r--. 1 user user 1093 4月 30 10:35 R1-Apr-30-14-35-09.006-5
-rw-r--r--. 1 user user 1073 4月 30 10:35 R2-Apr-30-14-35-08.939-4
-rw-r--r--. 1 user user 1093 4月 30 10:37 R1-Apr-30-14-37-52.197-6
-rw-r--r--. 1 user user 1073 4月 30 10:38 R2-Apr-30-14-38-09.972-5
-rw-r--r--. 1 user user 1093 4月 30 10:39 R1-Apr-30-14-39-17.723-7
-rw-r--r--. 1 user user 1093 4月 30 10:40 R1-Apr-30-14-40-53.180-8
-rw-r--r--. 1 user user 1073 4月 30 10:41 R2-Apr-30-14-41-10.819-6
-rw-r--r--. 1 user user 1093 4月 30 10:43 R1-Apr-30-14-43-54.061-9
-rw-r--r--. 1 user user 1073 4月 30 10:44 R2-Apr-30-14-44-10.959-7
-rw-r--r--. 1 user user 1093 4月 30 10:46 R1-Apr-30-14-46-54.980-10
-rw-r--r--. 1 user user 1073 4月 30 10:47 R2-Apr-30-14-47-11.101-8
-rw-r--r--. 1 user user 1093 4月 30 10:49 R1-Apr-30-14-49-56.023-11
-rw-r--r--. 1 user user 1073 4月 30 10:50 R2-Apr-30-14-50-11.460-9
-rw-r--r--. 1 user user 1106 4月 30 10:51 R1-Apr-30-14-51-57.355-12
-rw-r--r--. 1 user user 1106 4月 30 10:52 R1-Apr-30-14-52-56.856-13
-rw-r--r--. 1 user user 1073 4月 30 10:53 R2-Apr-30-14-53-11.594-10
-rw-r--r--. 1 user user 1083 4月 30 10:55 R1-Apr-30-14-55-58.039-14
-rw-r--r--. 1 user user 1073 4月 30 10:56 R2-Apr-30-14-56-11.761-11
-rw-r--r--. 1 user user 1083 4月 30 10:58 R1-Apr-30-14-58-59.227-15
-rw-r--r--. 1 user user 1073 4月 30 10:59 R2-Apr-30-14-59-11.901-12
-rw-r--r--. 1 user user 1105 4月 30 11:02 R1-Apr-30-15-02-00.102-16
-rw-r--r--. 1 user user 1073 4月 30 11:02 R2-Apr-30-15-02-12.252-13
-rw-r--r--. 1 user user 1105 4月 30 11:05 R1-Apr-30-15-05-00.981-17
-rw-r--r--. 1 user user 1073 4月 30 11:05 R2-Apr-30-15-05-12.392-14

BFDで高速切替

通常,ダイナミックルーティングを利用して経路の切り替わりを制御する場合,タイマーの値を調整して行いますが,せいぜい秒単位での切り替わりが限界です.

BFD(Bidirectional Forwarding Detection)(双方向転送検出)を使うとmsec単位での高速な経路切り替えが可能になるということで,検証.

https://tools.ietf.org/html/rfc5880

BDFには2つのモードがある.
ひとつはAsynchronous mode.
定期的にBFDコントロールパケットを送出し,対向側で受信されなくなったら,セッションダウンとなる.(対向側でダウンと検知する)
二つ目はDemand mode.
このモードは一度BFDセッションが確立されると,対向へのBFDコントロールパケットの送出を止める.

検証で使ったIOSではDemandモードの設定はなさそうだった.なので,Asynchorous Modeで動く.

設定は動かすだけなら凄く簡単.

1.インタフェースにBFDの定義を入れる
2.BFDを適用させるルーティングプロトコルへ設定する

以上の2ステップ.

簡単な構成を組んで動かす.

まずは普通にBGPでルーティングの設定.
テスト環境ではkeepalive 5, holddown 15とした.

R1抜粋

router bgp 64512
bgp log-neighbor-changes
network 10.10.10.0 mask 255.255.255.0
network 192.168.1.0
timers bgp 5 15
neighbor 10.10.10.2 remote-as 64513
neighbor 192.168.1.3 remote-as 64512
neighbor 192.168.1.3 next-hop-self
!

R2抜粋

router bgp 64512
bgp log-neighbor-changes
network 10.10.20.0 mask 255.255.255.0
network 192.168.1.0 route-map ATTACH_MED
timers bgp 5 15
neighbor 10.10.20.2 remote-as 64513
neighbor 192.168.1.2 remote-as 64512
neighbor 192.168.1.2 next-hop-self
!
!
ip access-list standard BGP_MED
permit 192.168.1.0 0.0.0.255
!
!
route-map ATTACH_MED permit 10
match ip address BGP_MED
set metric 10
!

R3抜粋

router bgp 64513
bgp log-neighbor-changes
network 10.10.10.0 mask 255.255.255.0
network 192.168.2.0
timers bgp 5 15
neighbor 10.10.10.1 remote-as 64512
neighbor 192.168.2.3 remote-as 64513
neighbor 192.168.2.3 next-hop-self
!

R4抜粋

router bgp 64513
bgp log-neighbor-changes
network 10.10.20.0 mask 255.255.255.0
network 192.168.2.0 route-map ATTACH_MED
timers bgp 5 15
neighbor 10.10.20.1 remote-as 64512
neighbor 192.168.2.2 remote-as 64513
neighbor 192.168.2.2 next-hop-self
!
!
!
ip access-list standard BGP_MED
permit 192.168.2.0 0.0.0.255
!
!
route-map ATTACH_MED permit 10
match ip address BGP_MED
set metric 10
!

それぞれのルーティングテーブルの状態.

R1#show ip route bgp
Codes: L - local, C - connected, S - static, R - RIP, M - mobile, B - BGP
D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area
N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2
E1 - OSPF external type 1, E2 - OSPF external type 2
i - IS-IS, su - IS-IS summary, L1 - IS-IS level-1, L2 - IS-IS level-2
ia - IS-IS inter area, * - candidate default, U - per-user static route
o - ODR, P - periodic downloaded static route, H - NHRP, l - LISP
a - application route
+ - replicated route, % - next hop override

Gateway of last resort is not set

10.0.0.0/8 is variably subnetted, 3 subnets, 2 masks
B 10.10.20.0/24 [200/0] via 192.168.1.3, 22:04:03
B 192.168.2.0/24 [20/0] via 10.10.10.2, 22:04:03
R2#show ip route bgp
Codes: L - local, C - connected, S - static, R - RIP, M - mobile, B - BGP
D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area
N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2
E1 - OSPF external type 1, E2 - OSPF external type 2
i - IS-IS, su - IS-IS summary, L1 - IS-IS level-1, L2 - IS-IS level-2
ia - IS-IS inter area, * - candidate default, U - per-user static route
o - ODR, P - periodic downloaded static route, H - NHRP, l - LISP
a - application route
+ - replicated route, % - next hop override

Gateway of last resort is not set

10.0.0.0/8 is variably subnetted, 3 subnets, 2 masks
B 10.10.10.0/24 [200/0] via 192.168.1.2, 22:04:10
B 192.168.2.0/24 [200/0] via 192.168.1.2, 22:04:01
R3#show ip route  bgp
Codes: L - local, C - connected, S - static, R - RIP, M - mobile, B - BGP
D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area
N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2
E1 - OSPF external type 1, E2 - OSPF external type 2
i - IS-IS, su - IS-IS summary, L1 - IS-IS level-1, L2 - IS-IS level-2
ia - IS-IS inter area, * - candidate default, U - per-user static route
o - ODR, P - periodic downloaded static route, H - NHRP, l - LISP
a - application route
+ - replicated route, % - next hop override

Gateway of last resort is not set

10.0.0.0/8 is variably subnetted, 3 subnets, 2 masks
B 10.10.20.0/24 [200/0] via 192.168.2.3, 22:04:28
B 192.168.1.0/24 [20/0] via 10.10.10.1, 22:04:29
R4#show ip route bgp
Codes: L - local, C - connected, S - static, R - RIP, M - mobile, B - BGP
D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area
N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2
E1 - OSPF external type 1, E2 - OSPF external type 2
i - IS-IS, su - IS-IS summary, L1 - IS-IS level-1, L2 - IS-IS level-2
ia - IS-IS inter area, * - candidate default, U - per-user static route
o - ODR, P - periodic downloaded static route, H - NHRP, l - LISP
a - application route
+ - replicated route, % - next hop override

Gateway of last resort is not set

10.0.0.0/8 is variably subnetted, 3 subnets, 2 masks
B 10.10.10.0/24 [200/0] via 192.168.2.2, 22:05:38
B 192.168.1.0/24 [200/0] via 192.168.2.2, 22:05:35

PC1~PC2間でPingを打ち続け,R1とR3のリンクをダウンさせる.

R1#show ip bgp neighbors 10.10.10.2 | inc hold time
Last read 00:00:02, last write 00:00:02, hold time is 15, keepalive interval is 5 seconds
Configured hold time is 15, keepalive interval is 5 seconds

なお,BGPの状態は設定通りに15秒keepaliveが無かったらネイバーをダウンとする設定となっている.
結果を見ると

PC1> ping 192.168.2.10 -t -w 10 -i 1000

84 bytes from 192.168.2.10 icmp_seq=1 ttl=62 time=1.646 ms
84 bytes from 192.168.2.10 icmp_seq=2 ttl=62 time=0.435 ms
84 bytes from 192.168.2.10 icmp_seq=3 ttl=62 time=0.541 ms
192.168.2.10 icmp_seq=4 timeout
192.168.2.10 icmp_seq=5 timeout
192.168.2.10 icmp_seq=6 timeout
192.168.2.10 icmp_seq=7 timeout
192.168.2.10 icmp_seq=8 timeout
192.168.2.10 icmp_seq=9 timeout
192.168.2.10 icmp_seq=10 timeout
192.168.2.10 icmp_seq=11 timeout
192.168.2.10 icmp_seq=12 timeout
192.168.2.10 icmp_seq=13 timeout
192.168.2.10 icmp_seq=14 timeout
192.168.2.10 icmp_seq=15 timeout
84 bytes from 192.168.2.10 icmp_seq=16 ttl=61 time=0.447 ms
84 bytes from 192.168.2.10 icmp_seq=17 ttl=61 time=0.490 ms
84 bytes from 192.168.2.10 icmp_seq=18 ttl=61 time=0.510 ms
84 bytes from 192.168.2.10 icmp_seq=19 ttl=61 time=0.460 ms
^C

およそ15秒程度で疎通が回復している.R1でDebugを有効にして状態を確認すると,

R1#show ip bgp neighbors 10.10.10.2 | inc hold time
Last read 00:00:14, last write 00:00:03, hold time is 15, keepalive interval is 5 seconds
Configured hold time is 15, keepalive interval is 5 seconds
R1#show ip bgp neighbors 10.10.10.2 | inc hold time
Configured hold time is 15, keepalive interval is 5 seconds
R1#show ip bgp neighbors 10.10.10.2 | inc hold time
*Mar 29 07:18:51.950: %BGP-3-NOTIFICATION: sent to neighbor 10.10.10.2 4/0 (hold time expired) 0 bytes
*Mar 29 07:18:51.950: %BGP-5-NBR_RESET: Neighbor 10.10.10.2 reset (BGP Notification sent)
*Mar 29 07:18:51.950: BGP(0): no valid path for 192.168.2.0/24
*Mar 29 07:18:51.950: %BGP-5-ADJCHANGE: neighbor 10.10.10.2 Down BGP Notification sent
*Mar 29 07:18:51.950: %BGP_SESSION-5-ADJCHANGE: neighbor 10.10.10.2 IPv4 Unicast topology base removed from session BGP Notification sent
R1#show ip bgp neighbors 10.10.10.2 | inc hold time
Configured hold time is 15, keepalive interval is 5 seconds
R1#

とちゃんと15秒で切り替わる動きをしている.

ここでBFDの定義を入れる.
Cisco IOSではインタフェース単位やテンプレートを作成してそれを元に画一的な定義を管理することができる.今回はシンプルにインタフェース事に設定する.
BFDの動作に関する主な設定パラメータは以下の通り.

 interval min-tx milliseconds min-rx milliseconds multiplier multiplier-value

「min-tx」で送信間隔,「min-rx」で受信間隔,「multiplier」でダウン検知とするkeepaliveパケットの数を指定する.

R1抜粋

interface Ethernet0/0
ip address 10.10.10.1 255.255.255.0
bfd interval 100 min_rx 100 multiplier 3 #追加
!
interface Ethernet0/1
ip address 192.168.1.2 255.255.255.0
standby 1 ip 192.168.1.1
standby 1 preempt delay minimum 5
bfd interval 100 min_rx 100 multiplier 3 #追加
!
!
!
router bgp 64512
bgp log-neighbor-changes
network 10.10.10.0 mask 255.255.255.0
network 192.168.1.0
timers bgp 5 15
neighbor 10.10.10.2 remote-as 64513
neighbor 10.10.10.2 fall-over bfd #追加
neighbor 192.168.1.3 remote-as 64512
neighbor 192.168.1.3 fall-over bfd #追加
neighbor 192.168.1.3 next-hop-self
!

R2抜粋

interface Ethernet0/0
ip address 10.10.20.1 255.255.255.0
bfd interval 100 min_rx 100 multiplier 3 #追加
!
interface Ethernet0/1
ip address 192.168.1.3 255.255.255.0
standby 1 ip 192.168.1.1
standby 1 priority 10
standby 1 preempt delay minimum 5
bfd interval 100 min_rx 100 multiplier 3 #追加
!
!
!
router bgp 64512
bgp log-neighbor-changes
network 10.10.20.0 mask 255.255.255.0
network 192.168.1.0
timers bgp 5 15
neighbor 10.10.20.2 remote-as 64513
neighbor 10.10.20.2 fall-over bfd #追加
neighbor 10.10.20.2 route-map ATTACH_MED out
neighbor 192.168.1.2 remote-as 64512
neighbor 192.168.1.2 fall-over bfd #追加
!

R3抜粋

interface Ethernet0/0
ip address 10.10.10.2 255.255.255.0
bfd interval 100 min_rx 100 multiplier 3 #追加
!
interface Ethernet0/1
ip address 192.168.2.2 255.255.255.0
standby 1 ip 192.168.2.1
standby 1 preempt delay minimum 3
bfd interval 100 min_rx 100 multiplier 3 #追加
!
!
!
router bgp 64513
bgp log-neighbor-changes
network 10.10.10.0 mask 255.255.255.0
network 192.168.2.0
timers bgp 5 15
neighbor 10.10.10.1 remote-as 64512
neighbor 10.10.10.1 fall-over bfd #追加
neighbor 192.168.2.3 remote-as 64513
neighbor 192.168.2.3 fall-over bfd #追加
neighbor 192.168.2.3 next-hop-self

R4抜粋

interface Ethernet0/0
ip address 10.10.20.2 255.255.255.0
bfd interval 100 min_rx 100 multiplier 3 #追加
!
interface Ethernet0/1
ip address 192.168.2.3 255.255.255.0
standby 1 ip 192.168.2.1
standby 1 priority 10
standby 1 preempt delay minimum 30
bfd interval 100 min_rx 100 multiplier 3 #追加
!
!
!
router bgp 64513
bgp log-neighbor-changes
network 10.10.20.0 mask 255.255.255.0
timers bgp 5 15
neighbor 10.10.20.1 remote-as 64512
neighbor 10.10.20.1 fall-over bfd #追加
neighbor 10.10.20.1 route-map ATTACH_MED out
neighbor 192.168.2.2 remote-as 64513
neighbor 192.168.2.2 fall-over bfd #追加
neighbor 192.168.2.2 next-hop-self

ステータス確認.(R1~R3間)

R1#show bfd neighbors details

IPv4 Sessions
NeighAddr LD/RD RH/RS State Int
10.10.10.2 4/4 Up Up Et0/0
Session state is UP and using echo function with 100 ms interval.
Session Host: Software
OurAddr: 10.10.10.1
Handle: 2
Local Diag: 0, Demand mode: 0, Poll bit: 0
MinTxInt: 1000000, MinRxInt: 1000000, Multiplier: 3
Received MinRxInt: 1000000, Received Multiplier: 3
Holddown (hits): 0(0), Hello (hits): 1000(612)
Rx Count: 617, Rx Interval (ms) min/max/avg: 1/1008/879 last: 681 ms ago
Tx Count: 613, Tx Interval (ms) min/max/avg: 755/1005/884 last: 681 ms ago
Elapsed time watermarks: 0 0 (last: 0)
Registered protocols: BGP
Uptime: 00:09:02
Last packet: Version: 1 - Diagnostic: 0
State bit: Up - Demand bit: 0
Poll bit: 0 - Final bit: 0
C bit: 0
Multiplier: 3 - Length: 24
My Discr.: 4 - Your Discr.: 4
Min tx interval: 1000000 - Min rx interval: 1000000
Min Echo interval: 100000

先ほどと同様にR1~R3間のインタフェースをダウンさせる.

PC1> ping 192.168.2.10 -t -w 10 -i 1000

84 bytes from 192.168.2.10 icmp_seq=1 ttl=62 time=0.480 ms
84 bytes from 192.168.2.10 icmp_seq=2 ttl=62 time=0.391 ms
84 bytes from 192.168.2.10 icmp_seq=3 ttl=62 time=0.478 ms
84 bytes from 192.168.2.10 icmp_seq=4 ttl=62 time=0.501 ms
84 bytes from 192.168.2.10 icmp_seq=5 ttl=62 time=0.414 ms
84 bytes from 192.168.2.10 icmp_seq=6 ttl=62 time=0.366 ms
84 bytes from 192.168.2.10 icmp_seq=7 ttl=62 time=0.412 ms
84 bytes from 192.168.2.10 icmp_seq=8 ttl=62 time=0.527 ms
84 bytes from 192.168.2.10 icmp_seq=9 ttl=62 time=0.439 ms
84 bytes from 192.168.2.10 icmp_seq=10 ttl=62 time=0.380 ms
84 bytes from 192.168.2.10 icmp_seq=11 ttl=62 time=0.499 ms
84 bytes from 192.168.2.10 icmp_seq=12 ttl=62 time=0.442 ms
84 bytes from 192.168.2.10 icmp_seq=13 ttl=62 time=0.420 ms
84 bytes from 192.168.2.10 icmp_seq=14 ttl=62 time=0.506 ms
84 bytes from 192.168.2.10 icmp_seq=15 ttl=62 time=0.495 ms
84 bytes from 192.168.2.10 icmp_seq=16 ttl=62 time=0.424 ms
84 bytes from 192.168.2.10 icmp_seq=17 ttl=62 time=0.445 ms
84 bytes from 192.168.2.10 icmp_seq=18 ttl=61 time=0.423 ms
84 bytes from 192.168.2.10 icmp_seq=19 ttl=61 time=0.653 ms
84 bytes from 192.168.2.10 icmp_seq=20 ttl=61 time=0.518 ms
84 bytes from 192.168.2.10 icmp_seq=21 ttl=61 time=0.677 ms
84 bytes from 192.168.2.10 icmp_seq=22 ttl=61 time=0.714 ms
84 bytes from 192.168.2.10 icmp_seq=23 ttl=61 time=0.690 ms
84 bytes from 192.168.2.10 icmp_seq=24 ttl=61 time=0.832 ms
84 bytes from 192.168.2.10 icmp_seq=25 ttl=61 time=0.741 ms
84 bytes from 192.168.2.10 icmp_seq=26 ttl=61 time=0.743 ms
84 bytes from 192.168.2.10 icmp_seq=27 ttl=61 time=0.693 ms
84 bytes from 192.168.2.10 icmp_seq=28 ttl=61 time=0.673 ms
84 bytes from 192.168.2.10 icmp_seq=29 ttl=61 time=0.630 ms
^C

R1のデバッグログ

R1#
*Mar 29 07:36:15.391: %BGP-5-NBR_RESET: Neighbor 10.10.10.2 reset (BFD adjacency down)
*Mar 29 07:36:15.395: BGP(0): no valid path for 192.168.2.0/24
*Mar 29 07:36:15.395: %BGP-5-ADJCHANGE: neighbor 10.10.10.2 Down BFD adjacency down
*Mar 29 07:36:15.395: %BGP_SESSION-5-ADJCHANGE: neighbor 10.10.10.2 IPv4 Unicast topology base removed from session BFD adjacency down
R1#
*Mar 29 07:36:15.400: BGP: topo global:IPv4 Unicast:base Remove_fwdroute for 192.168.2.0/24
*Mar 29 07:36:15.400: BGP(0): (base) 192.168.1.3 send unreachable (format) 192.168.2.0/24
*Mar 29 07:36:15.400: BGP(0): 192.168.1.3 rcvd UPDATE w/ attr: nexthop 192.168.1.3, origin i, localpref 100, metric 10, merged path 64513, AS_PATH
*Mar 29 07:36:15.400: BGP(0): 192.168.1.3 rcvd 192.168.2.0/24
*Mar 29 07:36:15.400: BGP(0): Revise route installing 1 of 1 routes for 192.168.2.0/24 -> 192.168.1.3(global) to main IP table

msecで切り替わるので,ログからは分からないが,インタフェースが落ちた瞬間にこのログが流れ見た目上もPingのパケロスは発生しなかった.
ちなみにインタフェースの切り戻りにおいてはBFDは効果がなく,BGPのタイマーに従って経路が戻る.これはBFDはルーティングプロトコルありきで動作する補助プロトコルであるためだと思われる.
BGPのネイバーが張られるまではBFDもアップにならない.


R1#show bfd summary

Session Up Down

Total 1 1 0
R1#
*Mar 29 08:08:01.616: %BGP-5-ADJCHANGE: neighbor 10.10.10.2 Up
*Mar 29 08:08:01.617: BGP(0): (base) 10.10.10.2 send UPDATE (format) 192.168.2.0/24, next 10.10.10.1, metric 10, path 64513
*Mar 29 08:08:01.617: BGP(0): (base) 10.10.10.2 send UPDATE (format) 10.10.20.0/24, next 10.10.10.1, metric 0, path Local
*Mar 29 08:08:01.617: BGP(0): (base) 10.10.10.2 send UPDATE (format) 192.168.1.0/24, next 10.10.10.1, metric 0, path Local
*Mar 29 08:08:01.618: BGP(0): 10.10.10.2 rcv UPDATE w/ attr: nexthop 10.10.10.2, origin i, originator 0.0.0.0, merged path 64513 64512, AS_PATH , community , extended community , SSA attribute
*Mar 29 08:08:01.618: BGPSSA ssacount is 0
*Mar 29 08:08:01.618: BGP(0): 10.10.10.2 rcv UPDATE about 192.168.1.0/24 -- DENIED due to: AS-PATH contains our own AS;
*Mar 29 08:08:01.618: BGP(0): 10.10.10.2 rcvd UPDATE w/ attr: nexthop 10.10.10.2, origin i, merged path 64513, AS_PATH
*Mar 29 08:08:01.618: BGP(0): 10.10.10.2 rcvd 10.10.20.0/24
*Mar 29 08:08:01.618: BGP(0): 10.10.10.2 rcvd UPDATE w/ attr: nexthop 10.10.10.2, origin i, metric 0, merged path 64513, AS_PATH
*Mar 29 08:08:01.618: BGP(0): 10.10.10.2 rcvd 10.10.10.0/24
*Mar 29 08:08:01.618: BGP(0): 10.10.10.2 rcvd 192.168.2.0/24
*Mar 29 08:08:01.618: BGP(0): Revise route installing 1 of 1 routes for 192.168.2.0/24 -> 10.10.10.2(global) to main IP table
R1#
*Mar 29 08:08:01.618: BGP(0): 192.168.1.3 NEXT_HOP is set to self for net 192.168.2.0/24,
*Mar 29 08:08:01.618: BGP(0): (base) 192.168.1.3 send UPDATE (format) 192.168.2.0/24, next 192.168.1.2, metric 0, path 64513
*Mar 29 08:08:01.623: BGP(0): 192.168.1.3 rcv UPDATE about 192.168.2.0/24 -- withdrawn
R1#
R1#show bfd summary

Session Up Down

Total 2 2 0
R1#

【娯楽】ESXiにWIn10をたててゲーミングPCとして利用する

背景

昨今の在宅の流れにより家のメインPCが夫婦で取り合いになる状況が多くなってきた。
それを受けて,新しくPCを新調することにした。
せっかくなのでゲームもできるPCにしようと小型ながらもゲームに耐えうるものを自作した。

そしてMHWがセールで安く売っていたので購入。
当然ながら奥様も「私もやる!」となる。しかしもう1台調達する資金は無い。最低限のパーツでもう1台準備するとなると・・・。

ということを考えた結果,ESXiのリソースが余っていたのでこれにGPUを積んでVMにパススルーさせればいけるだろうと思ったのが発端。

要件

  • 新しいPCはコスト的に手配は無理(調達するものは最低限に抑えたい)
  • 今のESXiのリソースを活用して仮想マシンで構築したい
  • ESXiがおいてある部屋とMHWをやる部屋は別なので,リモートアクセスしたい
  • タイムラグが無い操作感

<描いた構想>

<実際にできた構成>

結論から言うと,ESXi上のWin10へリモートアクセスしてやることかなわず, MHWをやるときにはESXiがある部屋に行ってやることになった。
できなかった理由は以下の通り。

  • コストを安く上げようと調達したOSがWinHomeであったためリモートデスクトップアクセスができなかった
  • TeamViewerやAnyDeskなどのリモートアクセスツールを試したが,USBのコントローラが利用できなかった
  • ESXiのリモートコンソールならUSB転送ができたが,反応がひどくて使い物にならない(そもそもグラフィックカード出力じゃないからダメ?)
最初からProを買っておけばもしかしたらいけたのかもしれないけど,買いなおすことは無駄なのでやめた。
ということで,結果的に必要となったものは
品名 参考価格
仮想マシン用OS Windows10 Home 64bit 15k
グラフィックカード 玄人志向 NVIDIA GeForce GTX 1650 15k
USBボード オウルテック USB3.0増設ボード 3k
ディスプレイ EVICIV 12.5インチ モバイルディスプレイ 28k
ゲームコントローラ PS4 コントローラー 2.5k
合計 63.5k

となかなかの出費になった。PS4買えるじゃんとも思ったが,Steam版との共闘ができないのでその線はなかった。

構築

いざ構築。手順は次の通り。

手順

  1. ESXiにグラボを搭載する
  2. 仮想マシン作成
  3. 仮想マシンオプション設定
  4. passthru.mapの編集
  5. OSインストール
  6. ESXi再起動
  7. 仮想マシン起動
<参考にしたサイト>
https://qiita.com/maeda_mikio/items/af538169d57bc89f6ca7
https://www.next-hop.net/~hiraga/VMware/esxi-gpupassthrough.shtml
https://qiita.com/strat/items/f741774d129206002cfc
https://www.vmware.com/content/dam/digitalmarketing/vmware/en/pdf/techpaper/vsp-4-vmdirectpath-host-technical-note.pdf

1. グラボ搭載

物理作業のため省略

2. 仮想マシン作成

Win10 Home64bitなのでWindowsのOSバージョンを選択する。

Windows 64ビットを選択

 Windows10 Homeは1ソケットしか対応していないのでコアは全部1つのソケットへ。

今回は4コアにした

仮想マシンオプションの詳細から「構成パラメータ」を設定する。

 「hypervisor.cpuid.v0」を「FALSE」で設定する。
このオプションにより仮想マシンに仮想CPUであることを隠せるらしい。それにより,OSにパススルーするグラフィックボードの(ドライバの)仮想環境チェックに引っかからず,エラーコード34回避に至る(と理解した)。

/etc/vmware/passthru.map を編集するため,ESX ShellとSSHサービスを有効化する。

3. OSインストール

WindowsのインストーラisoをCDドライブにマウントさせてインストールする。
※ vmware toolsもインストールしておいても良い

4. passthru.mapの編集

/etc/vmware/passthru.mapを以下のように編集する。
最後の行に

## NVIDIA
#10de ffff bridge false #コメントアウト
10de ffff d3d0 default #追記

以下のように個別に指定してもよい。

# Graphic
10de 1f82 d3d0 default #追記
# Audio
10de 10fa d3d0 default #追記

PCIデバイスリセット時の挙動を指定するオプションらしい。正直なところ分からなかったが,とりあえずここを設定しないとちゃんとグラフィックボードが機能しなかった。
ちなみにここで入力するデバイスIDとプロダクトIDは esxcfg-infoコマンドで確認できる。

5. ESXi 再起動

まさかこれが必要だとは思わず,3日くらい躓いていた。

6. PCIデバイスの接続

ESXi再起動後に仮想マシンへPCIデバイス(グラボとUSB)を付ける。

7. 仮想マシン起動

無事にグラフィックボードを認識してくれた。(ここまで本当に長かった・・・)
なお,公式サイトから最新のドライバをDLしてインストールするとまた認識してくれなくなった。

ドライバは自動でインストールされる
ちゃんと認識されている

参考にしたサイトではコンソール画面を無効化したりするなどしていたが,私はマルチディスプレイ設定でGeforceのみに出力する設定とした。

2だけを使う設定にしてコンソールは無効化

しかし問題も・・・

無事にうまくいったと思ったのもつかの間。
暫く放置する等でスリープ状態になったり,仮想マシンを再起動するとまたドライバがCode34エラーに陥ってしまう。こうなると再びVMをシャットダウンして,「VMの編集→PCIデバイスを外す→ESXiを再起動→VMへPCIデバイス取り付け」という手順を踏まなくてはならない。
これがまだ解決できていない。
なので当面はVMは絶対に落とさないという運用をすることになった・・・。

もう1つの問題はリモートの線がなくなったので,わざわざ部屋を移動してモンハンしなくてはならないという点か・・・。

とりあえずはサクサクMHWが動いたのでヨシとした。

無事MHWも起動。コントローラもサクサク動いた

GNS3サーバ1台を複数人で利用する

GNS3サーバを1台立てて, チームメンバー数人で利用する場合の環境を構築する方法のメモ。

イメージ

手順は以下の通り。

  1. GNS3サーバを建てる
    • ユーザ作成
    • 必要なパッケージ準備
  2. GNS3サーバをデーモンモードで起動
  3. 各人のPCにGNS3をインストール
  4. 接続先をサーバに指定する
1. GNS3 サーバ準備
インストール方法(公式)
ubuntu 18.04LTS で試したが, この公式の手順だとパッケージが見つからずインストールできなかった。

ということで, Discussionにあったpipを使えばいけるという情報を参考にセットアップする。

Unable to install GNS3 on Ubuntu 19.04

ubuntu@gns3:~$ sudo adduser gns3
ubuntu@gns3:~$ sudo apt install python3-pip
ubuntu@gns3:~$ sudo pip3 install gns3-gui gns3-server

2. デーモンモードで起動

ubuntu@gns3:~$ git clone https://github.com/GNS3/gns3-server.git
ubuntu@gns3:~$ cd gns3-server/init/
ubuntu@gns3:~/gns3-server/init$ sudo cp gns3.service.systemd /lib/systemd/system/gns3.service
ubuntu@gns3:~/gns3-server/init$ sudo chown root /lib/systemd/system/gns3.service
ubuntu@gns3:~/gns3-server/init$ sudo systemctl start gns3

3. クライアントセットアップ

オフィシャルページからGNS3をダウンロードしてインストール。

4. GNS3起動, 接続設定
起動後, 接続先サーバを「remote server」とする。

「Run application on a remote server」を選択

接続先のIPアドレス, 認証情報を入力。
今回はgns3ユーザで接続。
FirewallでTCP3080を開けておく。

無事接続できると, サーバ稼働状況がいつものように表示される。

以降, いつものように使いたいイメージを登録していけばOK。

ただし, 1つのユーザを複数人でシェアする環境となるため, イメージの作成・削除やプロジェクトの扱いは要注意。(うっかり人のプロジェクトを使ってしまったり, 削除してしまったりすると悲惨)
※ 共有フォルダと同じ感覚で取り扱うとよいと思われる。

なお, 同一プロジェクトを同時に利用しているとそれぞれの変更がリアルタイムで反映されるので, 検証を一緒にやりたいときなど便利かもしれない。

【メモ】EVE-NG on ESXi で外部アクセスを行うときの注意点

PCサーバにESXiをインストールして, その中にEVE-NGのVMをたて, NICを2枚つける。
一方は管理アクセス用, もう一方はEVE-NG内から外部アクセスを行うためのCloudネットワーク。

ここで, OpenStack上に立てていたEVE-NGでは問題なく(Promiscuous設定はOpenStack側でもallowed-address-pairs で設定が必要), ESXiのvswitchのセキュリティ設定で

・無差別モードを許可

だけでなく

・偽装転送を許可

する必要があった。

たしかにvNICの中から多数のMacアドレスが流れ出てくるのだからこれは必要か。

CentOS7にpyenv

そろそろ真面目にPythonに取り掛かろうと、環境準備の一貫で異なるバージョンのPython環境を揃えることができるpyenvをインストールする。

公式サイト(GITHUB)

依存関係準備

$ sudo yum install @development zlib-devel bzip2 bzip2-devel readline-devel sqlite 
sqlite-devel openssl-devel xz xz-devel libffi-devel findutils

インストール

$ git clone https://github.com/pyenv/pyenv.git ~/.pyenv

pyenvのPATH設定

$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
# Add pyenv init to your shell to enable shims and autocompletion. Please make sure eval "$(pyenv init -)" is placed toward the end of the shell configuration file since it manipulates PATH during the initialization.
$ echo -e 'if command -v pyenv 1>/dev/null 2>&1; thenn eval "$(pyenv init -)"nfi' >> ~/.bash_profile
$ source ./.bash_profile

完了。

確認

現状チェック。

$ python -V
Python 2.7.5

pyenv で3.7.0をインストール。

$ pyenv install 3.7.0
Downloading Python-3.7.0.tar.xz...
-> https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tar.xz
Installing Python-3.7.0...
Installed Python-3.7.0 to /home/centos/.pyenv/versions/3.7.0
$ pyenv versions
* system (set by /home/centos/.pyenv/version)
3.7.0

script directoryだけをversion 3.7.0 にする。

$ pwd
/home/centos/script
$ pyenv local 3.7.0
$ pyenv versions
system
* 3.7.0 (set by /home/centos/script/.python-version)
$ cd
$ pyenv versions
* system (set by /home/centos/.pyenv/version)
3.7.0

へー面白い。

【メモ】BIG IPでURL毎にPoolを分ける

F5 BIG IP LTMで1つのバーチャルサーバに対してURLで振り分け先(Pool)を変えるiRuleをかかなくてはならなくなったのでメモ。

参考にしたサイトはこちら。
BIG-IPで、Hostヘッダに基づいた振り分けを行うiRule3種
F5 official HTTP::uri

また, 動作イメージとして「www.xxx.yyy.com」というFQDNに対して, サイト1用とサイト2用のディレクトリを分けている状況を想定している。

www.xxx.yyy.com/siteA/  -> poolAへ
www.xxx.yyy.com/siteB/  -> poolBへ

when HTTP_REQUEST
{
# (1)
set uri [split [HTTP::uri] "/"]
# (2)
set uri1st [lindex $uri 1]
# (3)
if { [class match $uri1stp equals distribute_list] } {
set pool [class match -value $uri1st equals distribute_list]
pool $pool
}
# (4)
else {
# Default Pool
pool pool_def
}
}

iRuleと合わせて予めData Group Listを作成する。

処理の流れ。

  1. URI取得、スラッシュで区切りインデックス化
  2. FQDNの次にくる文字列を取り出す
  3. Data Group ListのStringにマッチしたとき, poolにマッチしたValueを返す
  4. そうでなければデフォルトのプール
色々調べると, 「start_with」などあるけれど, 今回は特定のディレクトリ配下で振り分け先を分けるケースを想定したのでこちらの方がよいのかなーなんて。
記録を残すことを目的としてまずは・・・。