YAMAHAルーター+lua scriptで簡易的な冗長構成を組んでみた
VRRPやHAが組めない異機種間で冗長構成を組みたかったのでlua scriptでなんとかしてみた
はじめに
我が家ではメインルーターとしてSophos XG FirewallがVMとして稼働している このルーターが利用できないときにYAMAHAルーターをバックアップとして自動的に利用するスクリプトを書いてみた
普通の冗長構成
HA構成(sophos XG Firewall)
HAは同機種間のみサポート。そのためHA構成を組む場合はXG Firewallがもう一台必要。我が家ではXGFirewall用にもう一台VMを用意するのがランニング的に見合わなかったので不採用
VRRP構成
標準規格なのでSophos XG - YAMAHA RTX間で組めるかなと思いきや、Sophos XG側で未対応
以上から自力で YAMAHAのlua script機能を利用して簡易的な冗長構成を作成することにした
構成
インターネットプロバイダの制約上、プロバイダ貸し出し機器以外へ直接グローバルIPを割り振れない構成上、少し特殊な構成になっている
Sophos XG側がDefaultGWになっており、このルーターがDHCP機能も兼ねている
よってYAMAHA RTXが障害時に担う役割は以下である * DefaultGWのIPを引き継ぐ * DHCPサーバー機能を稼働する
障害時の想定
障害時にはSophox XG側のlan側IP、wan側のIPが不通となる想定
設定
YAMAHA config
DHCP設定のみ投入し、サービスは無効 IPは.2設定(≒非defaultGW)
ip lan1 address 192.168.0.2/24 dhcp server rfc2131 compliant except remain-silent dhcp scope 1 192.168.0.50-192.168.0.100/24 gateway 192.168.0.1 -- recovery用スクリプト。後述 schedule at 1 startup * lua /scripts/recovery.lua
※ 関連箇所のみ抜粋
lua script
以下の動作を想定したスクリプト Primaryに昇格 1. default GW宛に疎通確認。疎通確認が取れない場合2へ 2. YAMAHA RTX側が外部疎通できるか確認。確認が取れたら3へ 3. IPをdefault GW(192.168.0.1)に差し替え、DHCP機能ON
Secondaryに降格 1. Sophos XG、WAN側IPへ疎通確認。疎通確認が取れた場合は2へ 2. YAMAHARTX側のIPを192.168.0.2へ、DHCP機能をOFF
recovery.lua
function check_loss_rate(ipaddress, count) command = "ping -c "..count.." "..ipaddress rt.syslog("debug","command:"..command) res, text = rt.command(command) rt.syslog("debug", "result:"..text) loss = string.match(text, "(%d+)%.%d+%%") if (loss ~= nil) then return tonumber(loss) end return 0 end function get_promoted() rt.command("dhcp service server") rt.command("ip lan1 address 192.168.0.1/24") rt.syslog("info", "primaryに昇格しました") end function get_relegated() rt.command("no dhcp service server") rt.command("ip lan1 address 192.168.0.2/24") rt.syslog("info", "secondaryに降格しました") end local local_gw = "192.168.0.1" local external = "8.8.8.8" local primary_wan_addr = "192.168.254.253" function execute() mode = "secondary" rt.syslog("debug", "start script mode:"..mode) while true do if mode == "secondary" then -- 内部接続チェック internal_loss_rate = check_loss_rate(local_gw, 5) if internal_loss_rate > 50 then -- 外部接続チェック external_loss_rate = check_loss_rate(external, 5) if external_loss_rate == 0 then get_promoted() mode = "primary" end end else -- primary稼働中 loss_rate = check_loss_rate(primary_wan_addr, 30) if loss_rate == 0 then get_relegated() mode = "secondary" end end end end execute()
RTX向けのAPI一覧は以下に一覧がある
scriptのアップロード
今回はSFTP機能でアップロードした
# SFTP接続 sftp 192.168.0.2 # script用dir作成 mkdir scripts # scriptの設置 put [ローカルのスクリプトDir]/recovery.lua recovery.lua
scriptのスケジュール(先述のconfigに記載済み)
今回は常駐型のscriptで記載しているのでルーター起動時に1度のみ起動すればOK そのため以下の記載とした
-- recovery用スクリプト。後述 schedule at 1 startup * lua /scripts/recovery.lua
YAMAHA上でlua scriptの操作
# scriptの実行 lua /scripts/recovery.lua # scriptの実行ステータス確認 show status lua # scriptの強制終了 terminate lua file /scripts/recovery.lua
注意点
本構成はあくまで簡易的な冗長構成のため、ダウンタイム数分程度発生する。 具体的には * sophos XG Firewallがダウンしたと検知されるまでの時間 * YAMAHA RTXがIP差し替え後、コンピューターのARPテーブルがXG FirewallのMACアドレスからYAMAHRTXのMACアドレスに書き換わる時間
ARPテーブルのキャッシュ期間はコンピューターによりまちまちで、自身の環境では * google home: キャッシュ数秒-30秒程度 * Mac: 2-3分程度
となり、実質的には上記のARPキャッシュ時間がダウンタイムの時間と大きく直結する
やってみて
殆どの人がそうだと思うが、luaスクリプトを書いた経験がなく基本文法を調べながら書く為時間が取られた。script言語であればnodejsやpythonでもかけるようにしてほしい。(パフォーマンス面でluaが優れているとの記載があったので難しいかもしれないが)
本格的にscriptを書くとなるとYAMAHA用APIのmockを書く必要があり、mock用のライブラリや開発環境を用意してくれれば実機コピー後に意図しない動作等を防ぐことができるのでなお嬉しい。
rt.command
で殆どすべてのコマンドが実行可能なのでできることはかなり広いが、上記のテスタビリティの理由によりユーザー向けには公式で出している設定例以外のスクリプトはあまり利用したくないなといった印象だった