見出し画像

FreeBSD にファイアウォールを設置

さくらインターネットのさくらの VPS にインストールした FreeBSD が、デフォルトのままだと外から見て丸裸の状態になっている。

このままだと外部からのよろしくないパケットなどが飛んできても無防備のままなので、簡易なものであるがファイアーウォールを設置する。

なおさくらの VPS では単純なプロトコルとポートを指定したホワイトリスト方式の超簡易ファイアウォールを用意してくれているので、それを使っても良い。


FreeBSD で pf


FreeBSD で使えるファイアウォールはいくつかあって、標準の推奨は ipfw になっているので ipfw を使っている人が多いと思う。

私は、OpenBSD由来の pf が好きなので昔からもっぱら pf ばかり使っている。性能的には kernel として実装されている ipfw のほうが高速だが、それほど複雑な処理をするのでなければ、pf でも十分なトラヒックを扱うことができる。

FreeBSD 13.1-RELEASE なら pf は標準でインストールされているので、設定ファイルを書くだけで使える。


/etc/pf.conf


pf の設定は、/etc/pf.conf に設置する。


これが、必要最低限の設定を行ったもの。


set skip on lo0
set skip on vtnet1

block log all

pass quick on lo0 keep state
pass quick on vtnet1 keep state

pass out quick proto { tcp udp } from any to any keep state

pass in proto tcp from any to any port 2222 flags S/SA keep state
pass in proto tcp from any to any port { 80 443 } flags S/SA keep state

pass in inet proto udp from any to any port 1985 keep state
pass in inet6 proto udp from any to any port 2029 keep state
pass in inet6 proto udp from any to any port 5353 keep state

pass inet proto icmp all
pass inet6 proto ipv6-icmp all

pf.conf の動作は上から順に設定を拾っていって、ルールにマッチングした行があれば設定を上書きしていく、という挙動になっている。

そしてなにも設定がマッチングしなければ、パケットを操作しない(素通し)という挙動になる。

よって、ブロックしたい挙動を一つずつ上げていくブラックリスト方式か、許可する挙動を列挙するホワイトリスト方式のどちらかで記述することになるが、今回はほとんどのサービスが動いていないので、ホワイトリスト方式にする。


set skip on lo0
set skip on vtnet1

まず、先頭行から。

pf はループバックインタフェイス(lo0)を含めてすべてのインタフェイス上で動作するので、外部との接続に使わない、lo0 や vtnet1(LAN のスイッチに接続指定ある)は動作から除外したいので、除外するインタフェイスとして指定する。


block log all

pass quick on lo0 keep state
pass quick on vtnet1 keep state

ホワイトリスト方式とするので、デフォルトをすべてのインタフェイスですべてのプロトコルですべての宛先で block とする。(log と書くことで、ブロックした内容をログで取得できるので、デバッグに使える。不要なら block all だけで良い)

pf ではデフォルトのままでよい項目は省略でき、この block all も、実際には、

block drop in proto { tcp udp } from any to any
block drop out proto { tcp udp } from any to any

のような内容(実際はもっとたくさんの項目がある)だが、あれこれデフォルトのままで良いので省略した結果、block all になっている。

pass quick on (インタフェイス名) keep state で、指定したインタフェイス上でのパケットのやりとり(in/out とも)は許可することを指定している。先頭で lo0 と vtnet1 については除外したので、この行は冗長なのでなくても同じように動作する。

quick を付けると、この行で条件がマッチすれば以下の行は無視するようになる。(下に書かれたルールで上書きされなくなる)


pass out quick proto { tcp udp } from any to any keep state

これはこのホストから外部へ出ていくパケットをすべて許可するという意味。もちろん、本来出してはいけない IPアドレスからのパケットを禁止するなど、こちらもルールを書くべきところではあるものの、さくらの VPS は上位のスイッチで厳密に不正なパケットが破棄されるので、ユーザは細かいことを考える必要はない。

keep state を付けることで、このパケットに対する戻りのパケット(IP的には、外部から内部の向き(in))に対する許可のルールを自動で生成する。


pass in proto tcp from any to any port 2222 flags S/SA keep state
pass in proto tcp from any to any port { 80 443 } flags S/SA keep state

ここが、このホストで提供するサービスに、外部から接続を許可する設定。

TCP/IP port 2222 は、sshd を動かしているため。(デフォルトは 22)

80、443 はそれぞれ http、https のためのポート。複数のポートで同じルールを記述する場合は、 { } を使うことでリスト形式で省略することができる。


pass in inet proto udp from any to any port 1985 keep state
pass in inet6 proto udp from any to any port 2029 keep state
pass in inet6 proto udp from any to any port 5353 keep state

ここはさくらインターネットの仕様のための記述で、さくらの VPS では各ホストの疎通を確認するため、UDP/IP 1895(HSRPv1)、2029(HSRPv2)でマルチキャストのアドレス宛にパケットを投げてきてこのパケットを破棄してしまうとインタフェイスがダウンしたと検知されて、以後、上位のスイッチからこのホストへのパケットが流れてこなくなる。

UDP/IP 5353 は mDNS で、不要かもしれないが一応、許可しておく。

余談だが、VPS環境から見える範囲では MACアドレスのベンダーは Cisco のものばかりになっている。各ユーザ用のセグメントは、VLAN を使っていると思うが VLAN は最大で 4,096個しか作れないので、このあたりの制限をどうやって回避しているのか興味がある。(L2スイッチの各ポートごとに 4,096 ずつだが、いまどきの L2スイッチはものすごく性能が良いので、4千個程度の仮想マシンインスタンスを収容する程度の使い方だとリソースが有り余ってくると思われるため)


pass inet proto icmp all
pass inet6 proto ipv6-icmp all

ICMP、ICMPv6 に関してもなんらかの制約をつけたほうが良いのかもしれないが、いまのところはすべてを許可する設定にしてある。

serviceコマンドで pf を restart すると設定が適用される。(ssh経由で作業していると切断されるので VNCコンソールから作業したほうが良い)


適用されたルールは、pfctl -sr コマンドで確認できる。


ログ


ブロックする項目でログを取得するようにしてあるので、ブロックしている様子を tcpdump コマンドで確認することができる。

ログは、pflog0 インタフェイス経由で取得できる。

# tcpdump -n -e -ttt -i pflog0


次から次へ、なんのポートを狙ってるのか謎のパケットがどんどんブロックされていく様が見れると思う。

次回はウェブサーバの設置に備えて、無料の SSL証明書を取得する方法を紹介する。


さいごに


技術的な小難しい話題でしたが、最後まで読んでいただいてありがとうございました。

よければ ↓ にある、♡ をクリックしていただけると励みになります。質問のコメントも歓迎です。

この記事が気に入ったらサポートをしてみませんか?