nftablesでiptables xt_recent を使えない
iptables でrecent モジュールを使って、閾値を設けることができる。
iptables -I INPUT -i eth2 -m conntrack --ctstate NEW -m recent --name fromList --set iptables -I INPUT -i eth2 -m recent --name fromList --second 5 --hitcount 1 --rcheck --reap -j REJECT
このような、モジュールによるマッチングと閾値処理をnftable ではどうするのか。
nftables ではrecent モジュールでマッチングができない。
そこでかわりに ipset を使って記録をする。
この目的に、nftablesで set
機能が使える・
(xt_recentは強引につかえなくもない、別記事に記載)
送信元IPアドレスを記録する
NTBL=sample-dymamic NSET=recent nft delete table $NTBL nft add table $NTBL nft add set $NTBL $NSET { type ipv4_addr\; flags timeout\; timeout 10m \; } nft add chain $NTBL prerouting { type filter hook prerouting priority mangle \; } nft add rule $NTBL prerouting set add ip saddr @$NSET nft list set $NTBL $NSET
timeout 10m
を入れているので、最終通信から10min で削除される。
prerouting
で通信にhook
し、rule
は prerouting 通過で add saddr
する。
一定数以上に接続があると止める。
単位時間あたり接続が、閾値を超えたら止めることができる。
nft add rule ip $NTBL prerouting ip saddr @recent limit rate over 1/minute drop
さらに、NEW
に限定する
nft add rule ip $NTBL prerouting ct state new ip saddr @recent limit rate over 1/minute drop
カウントもしておく
nft add rule ip $NTBL prerouting ct state new ip saddr @recent limit rate over 1/minute counter drop
単位は、second
minitute
hour
など
timeout / expires の違い
- timeout: 非アクティブがN秒続いたら削除
- expires: 登録してN秒経過したら無効・削除
プログラミングっぽく書くと
言い換えると次の判定である。
# Timeout if ( last_seen.timestamp + timeout.delta ) { delete entry } # Expires if ( registerd.timestamp + expires.delta ){ { delete entry }
リストを使って過去に記録のある通信だけ通す。
recent リスト(SET)を使って、記録された通信だけを通す。
nft add rule ip $NTBL postrouting ip daddr @recent mark set $MARK_VALUE nft add rule ip $NTBL postrouting meta mark != $MARK_VALUE drop
iptables recent と違って、ipset ( set ) を使うのため、利用方法がipset準拠である。特別なことはなにもない。
listen 0.0.0.0 している場合
ローカルプロセスで、listen 0.0.0.0 の場合はどのIPアドレスをSRC指定で応答するかよくわからない。そこで、Ingressなインタフェースにパケットを返すために、ソースIPを書き換える。
nft add chain myt mychain { type route hook output priority -150\; } nft add rule myt mychain meta mark 0x00000320 ip saddr set $eth1_address udp sport set $listen_port
このようにして、ソースIPを書き換えて、確実にパケットを応答すればいい。
TCPだとConnectionのSyn/ACKでみれるが、UDPだと上記のような応答書き換えを行う必要がある。OpenVPNやWiregaurdのようなソフトウェアを0.0.0.0でリッスンしている場合に有効な設定である。
まとめ
ipset に動的に追加削除できるのでとても便利である。
ipset のリストのメンテナンスできるWEB管理画面を作ってしまえば、WEB上からSSH許可を申請するなどの運用もできるわけで。そのリストの更新をパケットで単位で識別できる。
これで、SSHの通信が疎通した(特定の通信が通った)ら通信を許可できる。とても柔軟にグレートなファイアウォールが作れる。ipset 組み合わせでIPレイヤであれば今まで難しかったことが、可能になる。専用機でやっていたことや専用アプリライアスに不可能なことを可能にする、なんでもできる神機能ファイアウォールが作れる。