NetBSD Advent Calendar 2022 11日目の記事です。 今日はNPF(NetBSD Packet Filter)でMSSクランプ設定を行う手順を紹介しようと思います。
MTUとMSSクランプ
ネットワーク上で一度に送信できるデータの最大サイズを示す単位として、MTU(Maximum Transmission Unit)があります。この値は使用するネットワークの種類やVPNなどでカプセル化が行われた場合でそれぞれ異なります。例えば、イーサネットのMTUは1500オクテットとなっています。
ご家庭でインターネットに接続する場合は、PPPoE(Point-to-Point Protocol over Ethernet)という通信プロトコロルを用いることがあります。通常は回線事業者からレンタルされるHGW(ホームゲートウェイ)やONU(Optical Network Unit)がPPPoEを話してくれるのでユーザはこのプロトコルを意識する必要はありませんが、PCルータのように、自分でルータを構築する場合にはPPPoEまわりの設定を行うことになります。
さて、このPPPoEですが、Ethernetヘッダの後ろにPPPoEヘッダ(6オクテット)とPPPヘッダ(2オクテット)を付与したPPPoEフレームでやりとりします。そのため、このPPPoEヘッダの分だけMTUのサイズが小さくなります。MTUを超えるIPパケットはネットワークに流せないため、MTUを1500オクテットのままにしている場合は、パケットが通ったり通らなかったりという奇妙な挙動になります。分かりやすい例では、Webページを開いた際に、表示される画像があったりなかったりという場合があります。
このデフォルトのMTUから変更したい場合に用いるのがMSS(Maximum Segment Size)クランプという機能です。これにより、MTUを任意のサイズに調整することが可能になります。
NPFでのMSSクランプ設定
NPFでMSSクランプの設定は以下のようになります。 procedure
ブロックの中で normalize: "mas-mss" <任意のMTUサイズ>
の形で設定します。
一般的なファイアウォール(またはNAT実装)では、MSSクランプ機能は内部に組み込まれているものですが、NPFでは拡張機能の形でMSSクランプが実装されています。そのため、 procedure
で normalize
カスタムプロシージャを呼び出している、というイメージになります。
$ext_if = "pppoe0"
procedure "mss-clamp" {
normalize: "max-mss" 1400
}
group "external" on $ext_if {
pass stateful out final all apply "mss-clamp"
pass stateful in final all apply "mss-clamp"
}
procedureはapplyしないと適用されない
ここで一点だけ気をつける必要があります。 procedure
はあくまでもカスタムプロシージャの呼び出しを宣言するだけであるため、「ルールにマッチした際にプロシージャを適用する」という設定を併せて行う必要があります。
先述した設定にもあるように、ルール記述時に apply "mss-clamp"
を指定することで、設定したプロシージャが適用されます。
この例ではステートフルに通過するパケットに対してMSSクランプを提供する設定になります。
group "external" on $ext_if {
pass stateful out final all apply "mss-clamp"
pass stateful in final all apply "mss-clamp"
}
まとめ
NPFでのMSSクランプ設定について紹介しました。一般的なファイアウォールのルールではMSSクランプ設定をそのまま指定できますが、NPFでは拡張機能としてMSSクランプ機能が実装されているため、プロシージャ呼び出しを宣言しておき、併せてマッチしたルールの側でプロシージャの適用を設定するという使い方になります。