自宅サーバをArch Linuxに入れ替えたのでファイアウォールの設定

## 背景
#### OS入れ替えました
自宅サーバのOSを入れ替えました。
これまでは再び仕事をする事もあるだろうと思いCentOS 7を使っていたのですが「もういいんじゃないか」という神託に従い、Arch Linuxに入れ替えました。
15年ほど*BSDの世界にいたので、FreeBSDにするか、Gentoo LinuxにするかArch Linuxにするか悩みましたが、USBメモリにOS入れたいとか色々考えて簡単そうなArch Linuxを選択。

#### ファイアウォールの設定がわからん
Linuxには[複数のIPフィルタがある](https://wiki.archlinux.jp/index.php/%E3%83%95%E3%82%A1%E3%82%A4%E3%82%A2%E3%82%A6%E3%82%A9%E3%83%BC%E3%83%AB)が、実際にはほとんどが[iptables](https://wiki.archlinux.jp/index.php/Iptables)のフロントエンドとして動作しており、実態はiptablesか[nftables](https://wiki.archlinux.jp/index.php/Nftables)の二種類のみであると記載されています。
nftablesのほうが新しいと書かれており、そちらを使いたく思ったが**Arch Linuxはインストール時点でiptablesが依存関係により導入される**という事なので楽ちん志向によりiptablesでの設定を採択しました。

## 設定

#### 目的
ここでは以下を目的として据えます。

- 接続元は日本国内に限定する
- iptablesを用いてファイアウォールを設定する
- NICの変更なども考慮して柔軟性を確保する

#### ipsetの導入
まずはIPアドレスのグループ化を行うため、ipsetを導入しました。

```
# pacman -S ipset
# systemctl start ipset
# systemctl enable ipset
```

ipsetは複数のIPアドレスに名前を使てまとめるためのツールだそうです。
日本国内のIPアドレス一覧はGoogleで検索して[ここ](http://www.cgis.biz/tools/access/)で取得しました。キーボードマクロで以下のようなスクリプトを作成します。

```ipset-jplist.sh
#!/bin/sh

ipset create -exist JPLIST hash:net
ipset add JPLIST 1.0.16.0/20
ipset add JPLIST 1.0.64.0/18
ipset add JPLIST 1.1.64.0/18
ipset add JPLIST 1.5.0.0/16
    .
    .
    .
ipset add JPLIST 223.223.208.0/21
ipset add JPLIST 223.223.224.0/19
ipset add JPLIST 223.252.64.0/19
ipset add JPLIST 223.252.112.0/20
```

#### NICデバイス名の固定化

最近のLinuxでは、eth1,eth2というようなデバイス名は使われなくなってきているようで、Arch Linuxでも初期状態ではepなちゃらのような名前が付けられていました。
ただ、私の自宅サーバについているNICは3つともIntel製のチップを使っているため、これでは管理が難しい。

管理を容易にして運用上のミスを防ぐため、デバイス名にわかりやすい名前を付けます。デバイス名の管理はudevで行われるため、以下を編集します[^1]。

[^1]: systemd-networkdをネットワークマネージャとして用いるならば`.link`設定ファイルでも同様の設定が可能です。

```/etc/udev/rules.d/10-network.rules
SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="XX:XX:XX:XX:XX:XX", NAME="in01"
SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="YY:YY:YY:YY:YY:YY", NAME="in02"
SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="ZZ:ZZ:ZZ:ZZ:ZZ:ZZ", NAME="ex01"
```

命名規則として、内部ネットワークはin??、外部接続のNICはex??としています。
構想としては、内部ネットワークを通常のネットワーク、ストレージネットワークの二つに分けて運用を行いたいのですが、現状では内部ネットワークは一種類だけなのでin02として運用します。

ここでひとまず再起動させて設定を確認します。

```
# sync
# sync
# sync
# shutdown -r +1
# logout
```

再起動後、以下のようになっていれば設定完了です。

```
# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: in01: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether XX:XX:XX:XX:XX:XX brd ff:ff:ff:ff:ff:ff
    inet 192.168.125.220/24 brd 192.168.125.255 scope global noprefixroute in01
       valid_lft forever preferred_lft forever
    inet6 xxxx::xxxx:xxxx:xxxx:xxxx/64 scope link
       valid_lft forever preferred_lft forever
3: ex01: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether ZZ:ZZ:ZZ:ZZ:ZZ:ZZ brd ff:ff:ff:ff:ff:ff
    inet AAA.AAA.AAA.AAA/27 brd AAA.AAA.AAA.255 scope global noprefixroute ex01
       valid_lft forever preferred_lft forever
    inet6 aaaa::aaaa:aaaa:aaaa:aaaa/64 scope link
       valid_lft forever preferred_lft forever
4: in02: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether YY:YY:YY:YY:YY:YY brd ff:ff:ff:ff:ff:ff
    inet 192.168.125.53/24 brd 192.168.125.255 scope global noprefixroute in02
       valid_lft forever preferred_lft forever
    inet6 fe80::6a08:7a98:c26d:79f4/64 scope link
       valid_lft forever preferred_lft forever
```

我が家の内部ネットワーク第3オクテットは7年前に別れた恋人の誕生日(01/25)にちなんで125です。今さらネットワーク全体を工事するのも大変でずっとこれにしてるんですが、別れた恋人の名前がタトゥーになってる気分です。

#### iptablesを設定する

事前準備が整ったので、iptablesを設定します。
今回はipv6を使う予定はないので、編集する設定ファイルは`/etc/iptables/iptables.rules`です。
また、ポリシーとしては以下となります。

- 内部ネットワークは素通り
- 外部ネットワークは原則禁止
- SSHは日本国内からのみ許可
- 外部ネットワークはログを取得

よって、このように設定します。

```
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -i in0+ -j ACCEPT
-A INPUT -p icmp -j DROP

# SSH
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -m set --match-set JPLIST src -j ACCEPT

# log
-A INPUT -i ex0+ -j LOG

COMMIT
```

設定が完了したらiptablesを開始します。

```
# systemctl start iptables
```

外部からSSH接続できることも確認して、今日はひとまずここまで。