仮想マシン再起動時にsystemdで以ってiptablesのルールを保存・適用

OS: Ubuntu Server 18.04.1 LTS
VMware Workstation Pro 14.1.1 build-7528167

以前はifupdownでiptablesのルールを保存・適用していたけれどもnetplanの台頭によって近頃は流儀が異なるようである。netplanは2018年10月2日現在でif-up.dやif-down.dのような仕組みを持ち合わせていないからnetworkd-dispatcherで代替する手がある模様である。

ネットワークインターフェースが無効になった際に動き出すのは /usr/lib/networkd-dispatcher/off.d/ 配下に設置したスクリプトで、有効となった場合は /usr/lib/networkd-dispatcher/routable.d/ 配下のスクリプトであるという。

Netplan frequently asked questionsによる

ところがVMware上のUbuntu仮想マシンではoff.d配下のスクリプトが全然起動しなかった。スクリプトの所有権をrootにし、パーミッションも700にセットして必要条件を満たしてもどうしてもダメである。手動でネットワークインターフェースを無効にした場合は確かに実行されるけれどもどうもシャットダウンや再起動時には仮想マシンのネットワークが何故か無効にならない様子である。まるで原因がわからないからもうsystemdで以って対応した。

$ sudo vi /etc/systemd/system/iptables.service
[Unit]
Description=Save and restore iptables rules.
After=network.target
Before=shutdown.target reboot.target
Requires=network.target

[Service]
Type=simple
ExecStart=/bin/sh -c '/sbin/iptables-restore -c < /etc/iptables.conf'
ExecStop=/bin/sh -c '/sbin/iptables-save -c > /etc/iptables.conf'
RemainAfterExit=true

[Install]
WantedBy=multi-user.target

ExecStartやExecStopの項目ではリダイレクト記号を生で記述すると特別なものとして解釈されてしまうのか実行時にはリダイレクトが無いものとして振る舞っていた。これに気が付けずずいぶん悩んだものである。あとはユニットを有効にして終いである。

$ sudo /bin/sh -c '/sbin/iptables-save -c > /etc/iptables.conf'
$ sudo systemctl enable iptables.service
$ systemctl status iptables.service
● ipt-save.service - Save and restore iptables rules.
   Loaded: loaded (/etc/systemd/system/ipt-save.service; enabled; vendor preset: enabled)
   Active: active (exited) since Tue 2018-10-02 21:51:22 JST; 29min ago
(snip)

networkd-dispatcherは思い通りにならないしsystemdはなんだかとっつき難いし偉いものに首を突っ込んでしまったという心持ちである。

参考:
Use pre-up, post-up, etc. hook scripts
clayton craft / networkd-dispatcher・GitLab
Ubuntu Manpage: networkd-dispatcher – Dispatcher service for systemd-networkd connection status changes

ulogdで以ってiptablesのログを取得する

OS: Ubuntu Server 18.04 LTS
ulogd2 2.0.5-5

iptablesのログだけをひとところに集めて管理するならulogdが良さそうな様子であった。aptでシュッと入るのでたいへん楽ちんである。

$ sudo apt install ulogd2

デフォルトではふんだんにプラグインを読み取ってXMLで出力したりデータベースへ登録するなど有益な機能を提供する風情であるけれどもちょっと使い熟せそうにないので必要最小限の設定だけを残す。プラグインの設定はまず最初に plugin= の項目を記述してそのあと各々のプラグインの設定を書き記すという順番が肝要であった。順番を守らぬと決してulogdが起動しない。

$ sudo cp -av /etc/ulogd.conf /etc/ulogd.conf.orig
$ sudo vi /etc/ulogd.conf
[global]
logfile="/var/log/ulog/ulogd.log"
loglevel=3

plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_inppkt_NFLOG.so"
plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_filter_IFINDEX.so"
plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_filter_IP2STR.so"
plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_filter_PRINTPKT.so"
plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_output_LOGEMU.so"
plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_output_SYSLOG.so"
plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_raw2packet_BASE.so"

stack=log1:NFLOG,base1:BASE,ifi1:IFINDEX,ip2str1:IP2STR,print1:PRINTPKT,emu1:LOGEMU

[log1]
group=0

[emu1]
file="/var/log/iptables.log"
sync=1

設定を終えたらulogdがいざこざ無く起動するか確認しておく。起動しなければ journalctl -xe コマンドの出力や設定ファイルで指定したulogdのログ /var/log/ulog/ulogd.log の内容を精査して設定を修正する。

$ sudo systemctl start ulogd.service
$ sudo systemctl status ulogd.service
● ulogd2.service - Netfilter Userspace Logging Daemon
(snip)
Sep 24 16:10:17 server systemd[1]: Started Netfilter Userspace Logging Daemon.

滞りなく起動すればあとはiptablesの設定をする。--nflog-groupはulogd.confで設定したgroupの番号を指定し、--nflog-thresholdではulogdが処理を開始するまでにキューへ溜め込むパケット数を2から50の間で指定する。ulogdのドキュメントには--nflog-qthresholdと記載されている箇所もあるけれどもiptablesへ持ち込むと unknown option "--nflog-qthreshold" と木で鼻を括ったような態度であるから書き損じではないかとおもう。

$ sudo iptables -A INPUT -j NFLOG --nflog-group 0 --nflog-prefix 'iptables:' --nflog-threshold 20
$ tail -f /var/log/iptables.log
Sep 24 16:21:08 ubuntu kernel: [346292.067933] iptables: IN=eth1 OUT= MAC=00:0c:29:61:28:2a:74:03:bd:7f:5b:83:08:00 SRC=91.189.92.20 DST=192.168.0.150 LEN=40 TOS=0x08 PREC=0x00 TTL=42 ID=40114 DF PROTO=TCP SPT=443 DPT=52736 WINDOW=0 RES=0x00 RST URGP=0
(snip)

さらっぴんのiptablesへこの設定だけ放り込むと膨大な量のログで溢れ返って仕舞うから、正常に動作していることが確認できたら一旦設定を削除して改めて本番の設定をおこなうのが良さそうである。

$ sudo iptables -nvxL --line-numbers
Chain INPUT (policy ACCEPT 31 packets, 1936 bytes)
num      pkts      bytes target     prot opt in     out     source               destination
1          31     1936 NFLOG      all  --  *      *       0.0.0.0/0            0.0.0.0/0            nflog-prefix  "iptables:" nflog-threshold 20
$ sudo iptables -D INPUT 1

参考:
/usr/share/doc/ulogd2/ulogd.html
The netfilter.org “ulogd” project