二台のVPNクライアントがそれぞれ異なる公開IPv4アドレスから出ていくことがあります。それを実現するルールは多くの人が思うより短く、効いているのはiptablesの構文ではなくパケットが出口チェーンに届いたときの状態です。そこでの送信元アドレスがまだクライアントを区別できていなければなりません。先行するmasqueradeが両方を一つのアドレスにまとめてしまったなら、クライアント単位のルールでは区別を取り戻せないので、まずその問いを決着させてから変換を書いてください。

ゲートウェイまで生き残るのはどの身元か

ルールが照合するのはパケットの送信元アドレスであり、VPNのユーザー名でもクライアントアプリが表示する名前でもありません。経路上で先にパケットを変換するものが、ルールからまだ何が見えるかを決めます。natテーブルを順に実行し、送信元がまだクライアント単位である地点を見つけてください。

iptables -t nat -S POSTROUTING

その一覧を上から読んでください。上部近くのmasqueradeルールは一致するすべてのフローで送信元を書き換えるため、その後に置いたクライアント単位のエントリはもう存在しないアドレスと照合します。二台のLAN機器が一つのトンネルを共有し、単一の内部アドレスとして届く場合、送信元の範囲を分けたままにするか、それぞれに固有の内部アドレスを与えるよう、ファイアウォールより先に設計を変える必要があります。

内部アドレスの割り当ては、認証済みのクライアントに結び付けてください。そのアドレスを別の機器に渡すことは出口ポリシーも渡すことであり、送信元の変換だけでは身元の証明になりません。

変換はアドレスを発明できない

各公開アドレスはこの出口点に割り当てるか、ここへルーティングされている必要があり、応答はそこへ戻る道を見つけなければなりません。誰も戻りルートを持たないアドレスからトラフィックを送るルールは、遠端で破棄されるか、要求していないホストへ応答として届きます。クラウド事業者のインスタンスは通常、パケットが出る前に公開アドレスをプライベートインターフェースのアドレスへ変換しているため、SNATの送信元は事業者が受け付けるアドレスでなければならず、コンソールに表示される値ではありません。事業者のアドレスモデルを読み、公開値をすべてのパケットにコピーするのではなく、それに従ってください。

実際には、ファイアウォールに触れる前に事業者のコンソールでルーティング済みのプレフィックスを確認し、対応が一対一ならプライベートインターフェースのアドレスを変換の送信元に使うということです。以下の例で使うアドレスはドキュメント用の範囲から取っているので、最初に置き換えるのはアドレスの文字列そのものです。

汎用masqueradeの前に挿入する

何かを追加する前に、出口インターフェースと現在のチェーンを確認してください。前者はルールが照合できるパケットを決め、後者はその前に何がすでに立っているかを示します。

ip -4 route show default
iptables -t nat -L POSTROUTING -n -v --line-numbers

最初のコマンドは、インターネットへ向かうパケットが実際に出ていくインターフェースを名指しします。二つ目はチェーンを行番号付きで出力します。汎用masqueradeのエントリが、その上に留まるべき行です。

iptables -t nat -I POSTROUTING 1 -s 10.88.4.20/32 -o ens3 -j SNAT --to-source 198.51.100.77
iptables -t nat -I POSTROUTING 1 -s 10.88.4.21/32 -o ens3 -j SNAT --to-source 198.51.100.78

上の二つのルールはそれぞれ一つの内部アドレスに一致し、一致を出口インターフェースに限定し、送信元を明示的に設定します。追加ではなく挿入すると、位置 1 でmasquerade行より前に評価され、二つの順序は送信元が異なるため問題になりません。ens3 はrouteコマンドが報告した値に置き換えてください。二つのツールが一つのテーブルを書くことが正しいルールを効かなくする通常の理由なので、他のファイアウォール管理ツールは同じフックに近づけないでください。

新しいフローで送信元を証明する

ステートフルNATはフローの開始時に変換を結び付け、後続のパケットで再利用するため、変更前に開いたセッションは変更後も古い送信元を保ちます。ルールを証明できるのは新しく開始した接続だけです。

conntrack -L -s 10.88.4.20 -p tcp --dport 443

そのエントリの応答方向を読んでください。宛先は遠端が送信元として見ているアドレスなので、意図した公開アドレスと比較し、古いアドレスを持つエントリは、壊れたルールではなく開始が早すぎたフローの証拠として扱ってください。クライアントに新規接続を開かせてから、問い合わせを繰り返します。追跡テーブル全体をフラッシュしてテストを強制すると、ゲートウェイ上の他のすべてのセッションが中断されます。

変換は依然としてルートを選ばず、フィルタでフローを通さず、内向きサービスを公開しません。誤ったルートと欠けた許可ルールは、完璧なSNATルールの後でも失敗し続けます。IPv6と二次的な出口経路も確認し、次回の変更がルールの文面ではなく対応表から始まるよう、内部と公開の組をファイアウォールのドキュメントに記録してください。

関連記事