pfSenseのpfSctl

pfSenseはオープンソースのFWアプライアンスです。
WebGUIによる操作が可能で、FreeBSDベースのパッケージから有用なものがいくらか追加できるため、
単純なFW/ルータとしてだけでなく多機能なネットワークアプライアンスとして利用ができます。

さて、WebGUIによる操作ができる、と書きましたが実際にはWebGUIによる操作だけができるといったほうが現実に近いかもしれません。
冒頭さらっと触れたようにpfSenseはFreeBSDベースのアプライアンスなので、技術的にはコマンドライン操作で様々なことが実現できますが、
実際にはWebGUIからの操作と不整合を起こさずに済ませられることは多くありません。
あるいは設定の永続化などもWebGUIを前提にしているためコマンドラインでの操作は再起動後も正しく設定されていることが期待できないものもあります。

同様に、各種サービスやインタフェースの再起動に代表される運用的な操作についてもWebGUIから行うことになり、
FreeBSD的というか*nix的なサービスやインタフェースの直接stop/start, donw/upはおそらくサポートの対象外でしょう(まあOSSとして無償で使う限りはコミュニティサポートしかないのでユーザ間の情報交換の下で自己責任でやってしまうのでしょうが)。

ですが、実際にはpfSenseにはpfSctlというコマンドが含まれており、このコマンド経由での操作はpfSense的なインタフェースを通すのでこのコマンドを利用すれば様々な不整合を回避できると期待できます。

代表的なpfSctlの使い道はPPPoE接続のリセットです。
インタフェース設定でPPPoE接続を設定すると、Periodic resetの項目があることに気づくと思います。
cron的なスケジュール指定でPPPoEのインタフェースをリセットする機能なのですが、この機能でpfSctlが使われています。
(ちなみにcron的なスケジュール機能は実際にcronが使われています)
そのときに実行されるコマンドが下記です。

/usr/local/sbin/pfSctl -c 'interface reload wan'

wanの部分は実際のインタフェース名になります。pfSenseは文脈によって見た目上いろんなインタフェース名がつきますが、インタフェース設定画面のクエリストリングに指定されるものを書けば確実です。

さて、上記の例ではPPPoEのリセットが実行されましたが、個別にDown/Upをしたい(例えば一定時間の接続のあと次のタイミングまで切断しておきたい)場合はどうすればいいでしょうか。直感的には下記のようなものが思いつきます。

/usr/local/sbin/pfSctl -c 'interface stop wan'
/usr/local/sbin/pfSctl -c 'interface start wan'

しかしこれは間違っていて、期待通りに動作しません(期待通りもなにも、エラー以外の何も起きません)。
正解は下記です。

/usr/local/sbin/pfSctl -c 'interface linkup stop wan'
/usr/local/sbin/pfSctl -c 'interface linkup start wan'

この正解にたどり着くためにはソースを読む必要がありました。
pfSenseはOSSですからソースが公開されていて誰でも読むことができます。
早速 https://github.com/pfsense/pfsense をcloneしてきましょう。
アタリをつけて探っていくと src/usr/local/sbin あたりにソースが、、、ありませんね。
はてと思い、ではpfSctlを呼び出している側からヒントを得ようとしましたが、
いくらかの呼び出し側がみつかるだけで実体が見つかりません。
ここでGoogle先生にお伺いを立ててみると、どうやらpfSctlはportsパッケージとして別に管理されていることが分かりました。
なるほど名前はあたかもpfSenseっぽいけど、実際にはもっと汎用的なものだったのかー。
と思いつつ調査を進めると結局そのソースは https://github.com/pfsense/FreeBSD-ports にあるようです。
sysutils/check_reload_status というパッケージなのですね。pfSctl.cも見つかりました。
おやおやおや、、、

/*
 * pfSctl.c
 *
 * part of pfSense (https://www.pfsense.org)
 *(snip)
 */

結局pfSense用のパッケージなのでした。

ドキュメントらしいドキュメントも無いのでソースを斜め読みすると、server.hに対応コマンドの定義のようなものが列挙されています。
ここから推測して試しにいくつかのコマンドをたたいてみたところ、上記のように interface linkup {stop,start} IFNAME でPPPoEの切断と接続ができることがわかりました。おそらくですがinterfaceというコマンド名からPPPoEではないインタフェースでも停止と起動ができそうですね。試してないけど。

server.hを眺めてみるとインタフェース以外にサービスとフィルター(FW設定かな?)について操作ができるようです。
フィルターは実質一括reloadしかありませんが、サービスはpfSenseが持っている主要なサービスについて再起動ができるようです。困ったときにはこれで助かるケースももしかしたらあるかもしれません。