
2026/03/23 22:56
私の自宅ネットワークでは、OpenBSD と PF を使用して就寝時間を制御しています。
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
著者は、OpenBSD で pf を使用して動的「就寝時間」ファイアウォールルールを実装する方法について説明しています。
- pf はカーネルに組み込まれており、/etc/pf.conf で設定します。
- 2 つのテーブルが使用されます:<leased_ips>(dhcpd によって自動生成され、pf.conf の
として作成され、/etc/rc.conf.local のtable <leased_ips> persist counters
で有効化)と <bedtime_exempt>(テキストファイルからdhcpd_flags="-L leased_ips"
を使って更新)。pfctl -t bedtime_exempt -T replace -f no_bedtime.txt - 日中は、ルール
がトラフィックを許可します。夜間はアンカーがpass proto tcp from <leased_ips>
に切り替わります。アンカーは既存の接続を中断せずにオン・ザ・フライでルールを変更できるようにします。アンカーのルールに構文エラーがある場合、単にロードされず現在のトラフィックには影響しません。pass proto tcp from <bedtime_exempt> - デフォルトでは pf はアクティブなセッションを状態テーブルに保持します。就寝時間制限を即座に適用するために、スクリプトは
を使って該当するすべての状態エントリを削除します。著者はpfctl
から<leased_ips>
を差し引いた状態だけを殺す簡単な方法がないことを指摘しており、ルールにラベル付けしたり追加スクリプトを検討しました。<bedtime_exempt> - このアプローチにより、管理者は pf を再起動せずに時間帯ベースのネットワークアクセス制御(例:ゲストネットワーク、親権設定)を適用でき、長期間続く接続は状態クリアで管理できます。
本文
作家によるスケッチブックのインクと水彩画:
恐ろしいフッピーが通過すべきパケットを決定します。
私の設定の中心は、OpenBSD カーネルに組み込まれた pf パケットフィルタ です。この機能は OpenBSD 本来から存在し、
/etc/pf.conf に多くの pf 設定が記述されています。私は The Book of PF, 4th Ed. を読みながらゼロから自分用に構築しました(本ページ下部の参考文献を参照してください)。
設定全体はリポジトリ内で確認できます:
pf.conf。頻繁に触れない項目については徹底的にコメントを書き込み、pf を更新する手順も記載しています。
推奨構成
推奨される方法で設定しました:すべてのトラフィックをブロックし、必要なものだけを許可します。
-
昼間ルール
pass proto tcp from <leased_ips> -
就寝時ルール
pass proto tcp from <bedtime_exempt>
IP アドレステーブルは次の二つを使用します。
–<leased_ips>
がローカルネットワーク上でクライアントに IP を割り当てる際に管理されます。dhcpd
– 私が手動で管理。テキストファイルにアドレスを保存し、変更時にスクリプトでテーブルへロードします。<bedtime_exempt>
就寝中は除外対象のコンピュータへの通信のみ許可し、それ以外はデフォルトポリシー すべてブロック により遮断されます。
TCP のみを対象にしており、ICMP と UDP は書籍の指針通りに処理します。(更新:昼間ルールの実験が必要です—Discord の音声チャットや Roblox が機能しないため、一部メンバーから不満が出ました。)
テーブルの更新
<leased_ips> テーブルは pf.conf でプレースホルダーとして初期化します:
table <leased_ips> persist counters
dhcpd が /etc/rc.conf.local(リポジトリにもあります)に設定したコマンドラインオプションで自動的に埋められます:
dhcpd_flags="-L leased_ips"
<bedtime_exempt> のアドレスはテキストファイルに保存し、次のように更新します:
pfctl -t bedtime_exempt -T replace -f no_bedtime.txt
テキストファイルは1行に1アドレスを並べ、コメントは
# で付けることができます。テーブルが更新されると、カーネルの実行中テーブルに即座に反映され、pf を再ロードする必要はありません。
アンカー
就寝時の強制は、ローカルコンピュータからのトラフィックを許可するようスケジュールされたルール変更に依存します。アンカーは
pf.conf 内でルールをグループ化し、コマンドラインからリロードせずに置き換えることができる名前付きチャンクです。
anchor bedtime { # デフォルト「覚醒」ルール – 就寝時制御なし pass proto tcp from <leased_ips> }
アンカーを作成したら、ファイルや STDIN からそのルールを即座に置き換えることができます:
echo "block all" | pfctl -a foo -f -
アンカーのルールが置き換わると、pf はすぐにそれらを使用します。新規ルールに構文エラーがある場合は、pf が報告し無効なルールのみ無視して残りは継続実行されます。
ステートテーブルのアクティブ接続を削除
デフォルトでは pf はステートテーブルでアクティブな接続を追跡し、新しいルールがそれらを禁止しても接続を維持します。これは通常望ましい挙動です:
- 同じ接続内の各パケットを再度検査する必要がない。
- ルール変更やアドレステーブル更新時でも既存セッション(例:SSH)が継続できる。
私の場合は就寝時にトラフィックを遮断したい、特に YouTube の長時間ストリームなど。したがって、アンカーのルールを変更すると同時にローカルネットワーク上の接続を
pfctl で強制終了します:
# 実際のコマンドは省略
理想的には
<leased_ips> のエントリから <bedtime_exempt> を差し引いたものだけを対象にステートを削除したいです。man ページやウェブ、ソースコードを調べても簡単な方法は見つかりませんでした。可能性としては pf ルールにラベルを付けてラベルで接続を削除する―テーブルを利用して正しい接続リストを取得する「マッチ」ルールを作るなどがあります。あるいはスクリプト内で二つのテーブルの差分を計算する方法もありますが、手間が増えるでしょう。
最終スクリプト
上記すべてのステップを一つのシェルスクリプトにまとめています。