トンネルは上がり、ログインは成功し、ネットワーク上のすべてのホストが応答する。これは壊れたVPNではなく、権限モデルのないVPNである。RouterOSはアカウントを認証し、そのパケットを他の誰のものと同じようにルーティングするので、制限はファイアウォールが用意しなければならない。ログインを壊さずにその制限を加えることが、この作業のすべてである。

認証は権限が始まるところで終わる

PPPセッションが上がると、クライアントのパケットは他のどのインターフェースのトラフィックと同じようにforwardチェーンに入る。ルーターのforwardポリシーが寛容なら、コンサルタントはログイン時にその寛容さを引き継ぐ。アカウントは決してスコープを持っていなかったので、アカウント側で変えるものはない。ルールセットは従業員向けに書かれており、新しいセッションはただそれに加わった。

何かを書く前に、要求がどちらの経路の話かを確認する。 ルーターの背後のホストへのトラフィックはforwardを通る、一方、ルーター自身へのトラフィックはwinboxやSSHも含めてinputを通る。forwardだけを覆うスコープは、同じクライアントに対して機器を開いたままにする。

両方のチェーンに判断が必要で、たとえ判断がinputを閉じたままにすることでも変わりない。その選択はアクセス要求に属し、後付けの思いつきではない。

セッションを名前付きリストに結び付ける

PPPプロファイルは、セッション開始時に払い出すアドレスを名前付きアドレスリストに入れられる。これにより一時的なトンネルアドレスがファイアウォールで名前により照合できるものになり、セッションが終わるとエントリは消える。アカウントはアドレスを決め打ちするルールからではなく、プロファイルからスコープを引き継ぐ。

まずプロファイルを作成し、次にsecretを明示的にそれへ結び付ける。既定のプロファイルを指したままのsecretは元の問題を再現する。

プロファイルとリストの役割が明らかになるよう命名し、両方に要求の参照をコメントする。一つのプロファイルで同じスコープの複数人を扱え、リストは各セッションを識別し続ける。人ごとに一つのルールより見直しが安い。

/ppp profile add name=scoped-consultant remote-address=consultant-pool address-list=vpn-scoped-clients
/ppp secret add name=consultant password=... service=ovpn profile=scoped-consultant

許可するサービスを一つのリストに記録する

許可するサーバーをフィルタールールに埋め込むのではなく、専用のアドレスリストに入れる。リストは監査・拡張・コメントができ、サーバーが移ってもそれを使うルールは変わらない。一件だけでは過剰に見えるが、二台目が来れば普通のことになる。

アドレスが動的または負荷分散ならリストで照合し、予約済みで安定しているならアドレスを直接照合する。コメントにサービスと所有者を書けば、どちらでも明確に読める。

ホストだけでなくプロトコルとポートも絞る。ポート制限のないホストへのacceptは、そのホストが動かすすべてのサービスを開き、ほとんどのアクセス要求が意図するより広い。ポートは権限の一部であり、後から足す詳細ではない。

/ip firewall address-list add list=vpn-targets address=10.0.0.10 comment="consultant RDP target"

広いacceptより前にジャンプを並べる

ジャンプルールは、制限付きリストからの転送トラフィックを、ポリシー全体が三行に収まる専用チェーンへ送る。最初のルールが許可された宛先とポートを受理し、最後のルールが他をすべて落とす。ジャンプは、先のacceptがあると決して実行されないため、forwardのどの広いacceptよりも上に置く。戻りのトラフィックが流れるよう、establishedとrelatedのacceptはジャンプの前に置く。

fasttrackのルールがこのトラフィックを制限付きチェーンより先へ運べないことを確認する。fasttrackはフィルター経路の残りを迂回するので、fasttrackされた制限付きセッションはまったく制限されていない。

ルーター自身のサービスに到達できなくすべきなら、inputチェーンでも同じ判断を繰り返す。転送トラフィックを止めてwinboxを開いたままにするスコープは、半分しか終わっていない。

/ip firewall filter
add chain=forward action=jump jump-target=scoped-vpn src-address-list=vpn-scoped-clients
add chain=scoped-vpn action=accept protocol=tcp dst-address-list=vpn-targets dst-port=3389
add chain=scoped-vpn action=drop

カウンターとリストの所属で確認する

クライアントから許可されたサービスと失敗すべきサービスを試し、その後ルーターでルール統計を読む。acceptとdropのカウンターは各パケットがどの経路を通ったかを示し、それはクライアントからは見えない。稼働中のセッションのアドレスが制限付きリストに現れたことも確認する。

リストが空なら、アカウントが別のプロファイルにあるか、プロファイルがアドレスリスト設定を失っている。許可されたサービスが失敗するのにdropカウンターが増えるなら、宛先かポートがクライアントの送るものと一致していない。

何かを結論づける前に、同じサービスを名前とアドレスの両方で試す。名前解決の失敗は、クライアント側からはブロックされたポートとまったく同じに見える。そのうえでプロファイル、両方のリスト、唯一の許可サービスをアクセス要求に記録し、次のレビューが再構築ではなく比較できるようにする。

/ip firewall filter print stats where chain=scoped-vpn
/ip firewall address-list print where list=vpn-scoped-clients

関連記事