iptablesのログをrsyslogできちんと振り分ける

■iptablesのログをできちんと振り分ける。
 「rsyslog.conf」の扱いを誤魔化していたけど、ちょっと真面目に設定する。

■ダメなパターン1
 「syslogtag」を使って除外しよう設定した。

kern.debug                      /var/log/iptables.log
:syslogtag, contains, "iptables" ~

⇒結局全部「kern.debug」のコピーが
 以下の5倍ものログに出力されてしまっていた。

syslog.log
messages.log
debug.log
kern.log
iptables.log

■ダメなパターン2
 「kern.debug」全体を「iptables.log」に出力、「kern.debug」全体を除外しようとした。

kern.debug      /var/log/iptables.log
kern.debug ~

⇒ログの出力量は減ったけど、DNSSECや起動時のHWログ等、大事なデバッグログが迷子になった。
 デバッグログを「iptables.log」で見ること自体、おかしいです。。。

■結果として、「iptables」の単語では上手く行かなかったので、
 以下のように「IN=」という特徴的なログをキーにして「iptables.log」に出力、
 「& ~」で除外します。

$ sudo cat /etc/rsyslog.d/iptables.conf
:msg,contains,"IN="     -/var/log/iptables.log
& ~
$ sudo /etc/init.d/rsyslog reload

■loggerできちんと確認する。
 ※iptablesのログを偽装します。
  「s」オプションで画面にも出します。
  「sed」は無駄なことをしてますので、マニュアルをご確認下さい。

$ sudo logger -is -p kern.debug -t "kernel: " "iptables IN=eth0 OUT= \
MAC=XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX \
SRC=192.168.188.188 DST=192.168.188.88 LEN=60 \
TOS=0x00 PREC=0x00 TTL=128 ID=41786 PROTO=ICMP \
TYPE=8 CODE=0 ID=512 SEQ=4096" 2>&1 | sed s/" [A-Z]*=\{1,20\}"/"\n&"/g
kernel: [2327]: iptables
 IN=eth0
 OUT=
 MAC=XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
 SRC=192.168.188.188
 DST=192.168.188.188
 LEN=60
 TOS=0x00
 PREC=0x00
 TTL=128
 ID=41786
 PROTO=ICMP
 TYPE=8
 CODE=0
 ID=512
 SEQ=4096

⇒ありえないMACアドレスなので、探すのが簡単です。
 正しく「iptables.log」だけに出力されました。

$ sudo grep "XX\:XX" /var/log/*.log | awk -F\: '{print $1}' | sort -u
/var/log/iptables.log

■iptablesでも確認する。
 「auth.log」も見つかって一瞬ドキっとしましたが、sudoコマンドのログです。

$ sudo iptables -A INPUT -p icmp -m icmp -type 8 -j LOG --log-prefix "XX:XX iptables " --log-level 7
$ ping 192.168.188.188
...
$ sudo grep "XX\:XX" /var/log/*.log | awk -F\: '{print $1}' | sort -u
/var/log/auth.log
/var/log/iptables.log

$ sudo grep "XX\:XX" /var/log/auth.log | sed s/" [-A-z]*="/"\n&"/g
Sep  4 00:03:38 vmsqueeze sudo:  toor :
 TTY=pts/0 ;
 PWD=/home/toor ;
 USER=root ;
 COMMAND=/sbin/iptables -A INPUT -p icmp -m icmp
 -icmp-type=8 -j LOG --log-prefix XX:XX iptables  --log-level 7

■最後にもう一度確認します。

$ sudo grep ICMP /var/log/iptables.log | grep -v XX | tail -1 | \
  sed s/"[0-9a-f][0-9a-f]\:"/"XX\:"/g | sed s/" [-A-z]*="/"\n&"/g
Sep  3 XX:XX:25 vmsqueeze kernel: [2191]: iptables
 IN=eth0
 OUT=
 MAC=XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:00
 SRC=192.168.188.188
 DST=192.168.188.188
 LEN=60
 TOS=0x00
 PREC=0x00
 TTL=128
 ID=41786
 PROTO=ICMP
 TYPE=8
 CODE=0
 ID=512
 SEQ=40962012/09/05追記
 iptablesはログ出力に向いていない。
 出力しすぎて、取りこぼしたり除外設定が効かない場合もある。

 rsyslogの出力先を1つにするなど大胆な設計変更をしない限りは、
 最小の出力となるように調整し、「--log-level 1」とするべき。

 「デバッグ」用途のログではあるが、優先度は「インフォ」以下で、
 本当のデバッグをするなら、「tcpdump」や「snort」があります。

 一日で500万行のログの出力からたった数十行を取り出そうとするのではなく、
 一行も漏れなく欲しいログの出力に限定するべきだということにやっと気がついたのでした。。。

$ su root -c ' echo /var/log/*.log | \
  for list in `xargs` ;do \
    echo -n "$list : "; \
    grep "IN=" "$list" | \
    wc -l; \
  done' | grep -v " \: 0\$"
パスワード:
/var/log/iptables.log : 5058315