とりあえずnftablesを動かしてみた

# 0.はじめに
今後はiptablesに代わってnftablesが採用されるらしい。
>[来たるnftablesの概要などなど - Qiita](https://qiita.com/ryuichi1208/items/33e40e90b8747483ad9c)

firewalldに完全移行した人はバックエンドが変わるだけで気にする必要はないようだが、せっかくなのでnftalbesをさわってみる。
(ていうか自分がfirewalldに移行できていない)

CentOS8はまだリリース前なのでDebian10 "Buster"で試す。

# 1. 前提
- iptablesの知識はあるけどnftablesは知らない
- とりあえず動かしてみたい
- 何かあっても責任は負えません

# 2. 環境
ローカル仮想環境

- Linux debian10 4.19.0-6-amd64

# 3. nftablesを使ってみる
## インストール
```
 # apt install nftables
 # nft --version
nftables v0.9.0 (Fearless Fosdick)
```

## 起動
```
 # systemctl start nftables.service 
```
起動すると/etc/nftables.confが読み込まれるがこの時点では何もルールが設定されていない。

## サンプル
/usr/share/doc/nftables/examples/workstation.nftをコピーしてくる。
簡単なサーバーの場合、開放するポートさえ変更すれば十分そう。

- 変更後の/etc/nftables.conf

```
#!/usr/sbin/nft -f

flush ruleset

table inet filter {
        chain input {
                type filter hook input priority 0;

                # accept any localhost traffic
                iif lo accept

                # accept traffic originated from us
                ct state established,related accept

                # activate the following line to accept common local services
                tcp dport { 22, 80, 443 } ct state new accept
                # ↑の行のコメントアウトを外して、開放したいtcpポートを列挙

                # accept neighbour discovery otherwise IPv6 connectivity breaks.
                ip6 nexthdr icmpv6 icmpv6 type { nd-neighbor-solicit,  nd-router-advert, nd-neighbor-advert } accept

                # count and drop any other traffic
                counter drop
        }
}
```

## 再読込

```
# systemctl reload nftables.service
```

## NAT
/usr/share/doc/nftables/examples/nat.nftを読むとNATの設定方法も書いてある。

# 4. iptablesの設定をnftables用に変換

suin様の
>[俺史上最強のiptablesをさらす - Qiita](https://qiita.com/suin/items/5c4e21fa284497782f71)

にお世話になったので、これをnftableで使ってみます。

## inet -> ip に変更
nftablesはipv4とipv6をinetとしてまとめて扱えるのだが、とりあえず今はipv4だけを考える。
システムのipv6を無効化して、さらに/etc/nftables.conf内のinetをipに変更。

```
#!/usr/sbin/nft -f

flush ruleset

table ip filter {
	chain input {
		type filter hook input priority 0;
	}
	chain forward {
		type filter hook forward priority 0;
	}
	chain output {
		type filter hook output priority 0;
	}
}
```

## iptablesのインストールと設定
nftablesを一度とめてiptablesをインストール。

```
 # systemctl stop nftables.service
 # apt install iptables
```
suin様のスクリプトをほぼ素のまま実行(最後のfinalizeだけコメントアウトした)。

## nftables用に変換
iptablesの設定を一度ファイルに書き出します。

```
 # iptables-save > iptables.conf
```
(他のサーバーで動かしている場合はそっちから持ってきても可)

用意されてるコマンドでnftables用に変換します。

```
 # iptables-restore-translate -f iptables.conf > nftables.temp
```
(上記のコマンドが見つからなければiptablesをインストール)

### 注意点
大文字と小文字が区別されてしまうので、いま作成したnftables.temp内の
"INPUT", "OUTPUT", "FORWARD"を小文字にしておきます。

## 適用
nftablesを再度起動させ変換したルールを追加します。

```
 # systemctl start nftables.service
 # nft -f nftables.temp
```
## 確認

```
 # nft list ruleset
```

## 永続化
nftコマンドで一時的に追加したルールを永続化する場合はファイルに上書きしておきます。

```
 # nft list ruleset > /etc/nftables.conf
```

# 5. 最終的なnftables.conf

```
table ip filter {
	chain input {
		type filter hook input priority 0; policy drop;
		iifname "lo" counter packets 0 bytes 0 accept
		ip protocol tcp ct state established,related counter packets 60 bytes 4136 accept
		tcp flags & (syn | ack) == syn | ack ct state new counter packets 0 bytes 0 jump STEALTH_SCAN
		tcp flags & (fin | syn | rst | psh | ack | urg) == 0x0 counter packets 0 bytes 0 jump STEALTH_SCAN
		tcp flags & (fin | syn) == fin | syn counter packets 0 bytes 0 jump STEALTH_SCAN
		tcp flags & (syn | rst) == syn | rst counter packets 0 bytes 0 jump STEALTH_SCAN
		tcp flags & (fin | syn | rst | psh | ack | urg) == fin | syn | rst | ack | urg counter packets 0 bytes 0 jump STEALTH_SCAN
		tcp flags & (fin | rst) == fin | rst counter packets 0 bytes 0 jump STEALTH_SCAN
		tcp flags & (fin | ack) == fin counter packets 0 bytes 0 jump STEALTH_SCAN
		tcp flags & (psh | ack) == psh counter packets 0 bytes 0 jump STEALTH_SCAN
		tcp flags & (ack | urg) == urg counter packets 0 bytes 0 jump STEALTH_SCAN
		ip frag-off & 8191 != 0 counter packets 0 bytes 0 log prefix "fragment_packet:"
		ip frag-off & 8191 != 0 counter packets 0 bytes 0 drop
		icmp type echo-request counter packets 0 bytes 0 jump PING_OF_DEATH
		tcp flags & (fin | syn | rst | ack) == syn counter packets 0 bytes 0 jump SYN_FLOOD
		tcp dport { http, https } counter packets 0 bytes 0 jump HTTP_DOS
		tcp dport auth counter packets 0 bytes 0 reject with tcp reset
		ip daddr 192.168.1.255 counter packets 0 bytes 0 log prefix "drop_broadcast: "
		ip daddr 192.168.1.255 counter packets 0 bytes 0 drop
		ip daddr 255.255.255.255 counter packets 0 bytes 0 log prefix "drop_broadcast: "
		ip daddr 255.255.255.255 counter packets 0 bytes 0 drop
		ip daddr 224.0.0.1 counter packets 0 bytes 0 log prefix "drop_broadcast: "
		ip daddr 224.0.0.1 counter packets 0 bytes 0 drop
		ip protocol icmp counter packets 0 bytes 0 accept
		tcp dport { http, https } counter packets 0 bytes 0 accept
		tcp dport ssh counter packets 0 bytes 0 accept
		counter packets 0 bytes 0 log prefix "drop: "
		counter packets 0 bytes 0 drop
	}

	chain forward {
		type filter hook forward priority 0; policy drop;
	}

	chain output {
		type filter hook output priority 0; policy accept;
	}

	chain STEALTH_SCAN {
		counter packets 0 bytes 0 log prefix "stealth_scan_attack: "
		counter packets 0 bytes 0 drop
	}

	chain PING_OF_DEATH {
		icmp type echo-request meter t_PING_OF_DEATH size 65535 { ip saddr timeout 5m limit rate 1/second burst 10 packets}  counter packets 0 bytes 0 return
		counter packets 0 bytes 0 log prefix "ping_of_death_attack: "
		counter packets 0 bytes 0 drop
	}

	chain SYN_FLOOD {
		tcp flags & (fin | syn | rst | ack) == syn meter t_SYN_FLOOD size 65535 { ip saddr timeout 5m limit rate 200/second burst 3 packets}  counter packets 0 bytes 0 return
		counter packets 0 bytes 0 log prefix "syn_flood_attack: "
		counter packets 0 bytes 0 drop
	}

	chain HTTP_DOS {
		tcp dport { http, https } meter t_HTTP_DOS size 65535 { ip saddr timeout 5m limit rate 1/second burst 100 packets}  counter packets 0 bytes 0 return
		counter packets 0 bytes 0 log prefix "http_dos_attack: "
		counter packets 0 bytes 0 drop
	}
}
```
これを元にnftablesの文法を勉強しようと思います。

# 参考サイト
[Red Hat Enterprise Linux 8 新機能をわかりやすく解説](https://hackers-high.com/linux/rhel8-new-features/#iptables_nftables)