OpenVPNクライアントのブロックルールがFORWARDに届かない理由
クライアント間の通信はOpenVPNプロセス内にとどまり、ホストのFORWARDチェーンを通らないことがあるため、カウンターがゼロでも何も証明できない。
同じOpenVPNサーバー上の二つのクライアントは、プールに対してDROPルールを追加したあとでも互いに到達できる。ルールはFORWARDチェーンにあり、通信は明らかに流れているのに、そのルールのカウンターはゼロのままである。当然の結論はファイアウォールが壊れているということだ。しかし多くの場合、パケットはそもそもチェーンに入っていない。
OpenVPNサーバーを通過するピアパケットには二つの経路があり、どちらになるかはファイアウォールではなく設定で決まる。どちらの経路が使われているかを知れば、ホストのルールが正しい場所にあるのかどうかがわかる。
ピアパケットが取りうる二つの経路
内部転送オプションが無効の場合、クライアントAからのパケットは、クライアントBに割り当てられたアドレス内を宛先としてトンネルインターフェースに到着する。サーバーのルーティングテーブルは、Bのアドレスへのルートをサーバーが持っているため、同じトンネルインターフェースへ送り返す。これはホストを通る入出力のフローであり、IPv4転送経路がそれを評価する。
内部転送オプションが有効の場合、サーバープロセスはパケットを接続中のクライアントと突き合わせ、そのクライアント自身へ直接書き戻す。パケットはデーモン内部で処理され、トンネルデバイスに再び入ることはないため、ホストの転送経路は完全に飛ばされる。OpenVPN 2.6のマニュアルはこのオプションを内部クライアント間転送と説明しており、ホストのファイアウォールルールがそれを見られない理由はまさにここにある。
データチャネルをカーネルモジュールへオフロードする構成には第三の形態がある。転送の判断と暗号化がユーザー空間から出て、netfilterがそのフローを見るかどうかはオフロード経路の作り方に依存する。古いルールセットがオフロードされたサーバーでユーザー空間のサーバーと同じように振る舞うと決して仮定してはいけない。モードはパッケージのバージョンではなく、稼働中の設定から確認すること。
カウンターがまったく動かないとき
カウンターがゼロということは、その時点でパケットがそのルールに一致しなかったということで、理由はいくつかある。第一は前述のバイパスで、通信はチェーンに届いていない。第二はインターフェース、方向、送信元、宛先の不一致で、プールが採番し直されたのにルールが古いプレフィックスを指したままの場合によく起きる。
第三は位置である。チェーンの前方にあるルールが、あなたのDROPが評価される前にフローを受け入れているかもしれないし、後方のルールが実際に結果を決めているかもしれない。カウンターを見える状態でチェーンを順に読み、テストを繰り返したときにどのルールの数が増えるかを確認する。
実際のアドレスをサーバー自身の状態から確認した二つのクライアントの間で、覚えているリースではなくサーバーの状態から確認したうえで、統制された交換を一度行う。該当するカウンターがそれでも動かなければ、一致条件を書き換える前に経路を疑う。動くのに接続が成功するなら、ドロップは後段で上書きされており、問題は順序にある。この答えが、修正がルールの変更なのかトポロジーの変更なのかを決めるので、何かを編集する前に手に入れること。
フィルタできる境界を選ぶ
ポリシーをどうしてもホストのファイアウォールに置くなら、ファイアウォールが見える場所に通信を置くことだ。内部転送を無効にすることが、ピア間の通信をトンネルインターフェースと転送経路に通すためのサポートされた方法であり、代償としてすべてのピアパケットがホストのスタックを通る。
次にフローを正確に一致させる。通信は両方向ともトンネルインターフェースに到着し、トンネルインターフェースから出ていくので、物理インターフェースだけを見るルールは一致しない。アドレスベースのルールには現在のプールが必要で、往路だけでなく復路も考慮しなければならない。
多くの構成では、クライアントやグループのレベルでフィルタするほうが適している。そこでは身元が既知であり、ポリシーは再接続で変わるアドレスではなく利用者に従うが、これはホストのチェーンとは別の仕組みであり、明確な理由なしに両者を混ぜるべきではない。
古いトポロジーのルールセットを移行の際にそのまま持ち込まないこと。アドレスプール、インターフェース名、転送モードはどれもルールが一致するかどうかに影響し、以前動いていたコピーしたルールは最も誤解を招く種類の証拠である。許可したいフローから始めて、それに一致するルールを書くこと。
ルールを信じるのではなく分離を検証する
禁止される場合と許可される場合を同じ実行で試す。一方のクライアントから他方へ新しい接続を開始し、それが失敗することを確認し、そのうえで許可されるべき接続が今も機能することを確認する。前者だけを試すと、すべてを遮断するファイアウォールが成功に見えてしまう。
サーバー設定を再読み込みしたあとと、クライアントが再接続したあとに繰り返すこと(内部転送とプール割り当ては実行時の状態だからだ)。カウンターは両方向で確認するが、片方向に一致して応答に一致しないルールは部分的な分離を生み、素早いテストでは気づきにくい。
分離とは、実際にフローを運んでいる境界で観測される結果である。ホストのどこかにあるDROPルールは証拠ではないが、失敗した接続と、それを引き起こしたルールのカウンターの移動が証拠である。