firewall-cmdの使い方 はじめの一歩

Firewalldの設定値確認
================================

確認の流れ
------------------------------------------

ポイントは 「firewalldは Zoneを定義し、そのZoneの設定をNIC毎に適用すること」 です。
そのため、まずはじめにすることは、以下の２つです。

- ActiveなZone名の確認: 明示的にNICが登録されているゾーン
- DefaultのZone名の確認: 上記以外のNICが自動的に登録されるDefaultのゾーン

各NICに適用されているZone設定が確認できたら詳細を確認します。

- Active Zoneの詳細設定内容を確認。
- それ以外のNICはDefault　のZone設定が適用されることになるため、その設定状況を確認

では、下記より具体的にその確認方法を見ていきましょう。

存在するZoneの確認
------------------------------------------

まずは、どのようなZoneがあるか確認してみましょう。
firewalldでは初期状態で9種類のゾーンがテンプレートとして用意されています。通常はこれらのどれかのZoneをNICを適用し、場合に応じてチョイ替えすることから始めるのが良いでしょう。
9つの用途については "[CentOS7徹底入門 -firewalld- 1/2](https://www.nedia.ne.jp/blog/tech/2015/10/13/6031)" を参照すると良いでしょう。

```bash:command
firewall-cmd --get-zones
```

```text:response
block dmz drop external home internal public trusted work
```

Active Zone の名前確認
-------------------------------------------

定義されたZoneがNICに適用されている場合、これで具体的なZone名が得られます。この例ではtrusted zoneがeno3に対して割り当てられています。trusted zoneに変更を加えていなければ、eno3のNICはすべての通信をallowすることになります。

```bash:command
firewall-cmd --get-active-zones
```

```text:response
trusted
  interfaces: eno3 ib0
```

Default Zoneの名前確認
-------------------------------------------

上記のActive ZoneのようにNICに対して明示的にZoneを割り当てない場合、このDefault Zoneが適用されます。
eno3以外のNICはこの設定が適用されます。

```bash:command
firewall-cmd --get-default-zones
```

```text:response
public
```

特定のZoneの設定状況を確認
-----------------------------------------

それでは、この例における Activeである trusted zoneの設定状況を確認しましょう。この例では、設定自体はtrusted zoneの初期設定から変更がないことがわかります。`interfaces` には実際に登録されているNICの情報が見て取れます。

```bash:command
firewall-cmd --list-all --zone=trusted
```

```text:response
trusted (active)
  target: ACCEPT
  icmp-block-inversion: no
  interfaces: eno3 ib0
  sources: 
  services: 
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 
```


それでは、この例における Default Zoneであるpublicの設定状況を確認しましょう。この例では初期設定からports設定が追加されています。

```bash:command
firewall-cmd --list-all --zone=public
```

```text:response
public
  target: default
  icmp-block-inversion: no
  interfaces: 
  sources: 
  services: dhcpv6-client ssh
  ports: 6817/tcp 6818/udp 6818/tcp 6817/udp 8443/tcp
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 
```

すべてのZoneの設定状況を確認
-----------------------------------------

念のため最後の全体の設定状況をもう一度確認してみます。
すべての設定状況は以下で確認できます。(返り値は長いため省略)

```bash:command
firewall-cmd --list-all-zones
```


Firewallの基本的な設定方法
================================

設定の流れ
------------------------------------------

前述の通りfirewalldでは9種類のゾーンがテンプレートとして用意されています。通常はこれらのどれかのZoneをNICを適用し、場合に応じてチョイ替えすることになります。ここでは下記の設定方法を学びます。

デフォルトで用意された9つのゾーンをそのまま適用する

- Default Zoneの変更
- NICのZoneへの登録

ActiveもしくはDefaultのZoneに対してカスタマイズする

- 許可ポートの追加/削除
- 許可サービスの追加/削除


Default Zoneの変更
-------------------------------------------

前述のように9種類のゾーンがテンプレートとして始めから用意されており、これらはすでに用途に応じて機能します。
用途については "[CentOS7徹底入門 -firewalld- 1/2](https://www.nedia.ne.jp/blog/tech/2015/10/13/6031)" を参照すると良いでしょう。
まずはこの９つのゾーンの中から指定のZoneへDefaultを変更してみます。

```bash:command
ZONE_NAME="internal"
firewall-cmd --set-default-zone=${ZONE_NAME}
```

```text:response
success
```

ただしく設定されたことを確認します。

```bash:command
firewall-cmd --get-default-zone
```

```text:response
internal
```

NICを所望のzoneへ登録する (ZoneのActive化)
-------------------------------------------

前述のとおり、NICをあらかじめ定義したzoneへ登録することで、そのzoneの設定をNICに適用することができます。
`eno1`のNICを`public` zoneへ登録してみます。

```bash:command
NIC_NAME="eno1"
ZONE_NAME="public"
firewall-cmd --change-interface=${NIC_NAME} --zone=${ZONE_NAME}
```

```text:response
success
```

ただしく設定されたことを確認します。

```bash:command
firewall-cmd --get-active-zone
```

```text:response
public
  interfaces: eno1
trusted
  interfaces: eno3 ib0
```

もし、登録を解除する場合は `--change-interface` を `--remove-interface` のオプションに変更して同様のコマンドを実行してみてください。

許可ポートの追加/削除
-------------------------------------------

### 追加

ここでは例としてtcpの10022から10025を許可ポートとしてzone名 `dmz` に登録してみます。この例ではdmzは初期状態を維持しておりカスタマイズされていません。

- もしzone指定しない場合は、`default` のzoneに設定されます。 
- `default` zoneの確認は、`firewall-cmd --get-default-zone` を実行してください。

```bash:一時的設定
ZONE_NAME="dmz"
PORTS="10022-10025/tcp"
firewall-cmd --add-port=${PORTS} --zone=${ZONE_NAME}
```

```text:response
success
```

永続的に設定する場合は `--parmanent` オプションをいれ、実行後 `--reload` を実行してください。

```bash:永続的設定
firewall-cmd --add-port=${PORTS} --zone=${ZONE_NAME} --parmanent
firewall-cmd --reload
```

設定状況を確認します。

```bash:command
firewall-cmd --list-ports --zone=${ZONE_NAME}
```

```text:response
10022-10025/tcp
```

### 削除

```bash:一時的設定
ZONE_NAME="dmz"
PORTS="10022-10025/tcp"
firewall-cmd --remove-port=${PORTS} --zone=${ZONE_NAME}
```

```text:response
success
```

永続的に設定する場合は `--parmanent` オプションをいれ、実行後 `--reload` を実行してください。

```bash:永続的設定
ZONE_NAME="dmz"
PORTS="10022-1025/tcp"
firewall-cmd --remove-port=${PORTS} --zone=${ZONE_NAME} --parmanent
firewall-cmd --reload
```

設定状況を確認します。

```bash:command
firewall-cmd --list-ports --zone=${ZONE_NAME}
```

```text:response
(設定値なし)
```


許可サービスの追加/削除
-------------------------------------------

### 追加

ここでは例としてhttpsのサービスをzone名 `dmz` に登録してみます。この例ではdmzは初期状態を維持しておりカスタマイズされていません。

```bash:一時的設定
ZONE_NAME="dmz"
SERVICE="https"
firewall-cmd --add-service=${SERVICE} --zone=${ZONE_NAME}
```

```text:response
success
```

永続的に設定する場合は `--parmanent` オプションをいれ、実行後 `--reload` を実行してください。

```bash:永続的設定
firewall-cmd --add-service=${SERVICE} --zone=${ZONE_NAME} --permanent
firewall-cmd --reload
```

設定状況を確認します。httpsが追加されていることがわかります。

```bash:command
firewall-cmd --list-services --zone=${ZONE_NAME}
```

```text:response
https ssh
```

### 削除

```bash:一時的設定
ZONE_NAME="dmz"
SERVICE="https"
firewall-cmd --remove-service=${SERVICE} --zone=${ZONE_NAME}
```

```text:response
success
```

永続的に設定する場合は `--parmanent` オプションをいれ、実行後 `--reload` を実行してください。

```bash:永続的設定
firewall-cmd --remove-service=${SERVICE} --zone=${ZONE_NAME} --permanent
firewall-cmd --reload
```

```bash:command
firewall-cmd --list-services --zone=${ZONE_NAME}
```

```text:response
ssh
```

応用編
=============================


ダイレクトルールの確認
-----------------------------------------

説明は省きますが、IPマスカレードの設定されているときなどの確認に使います。

```bash:command
firewall-cmd --direct --get-all-rules
```

```bash:response例
ipv4 nat POSTROUTING 0 -o eno2 -j MASQUERADE
ipv4 filter FORWARD 0 -i eno1 -o eno2 -j ACCEPT
ipv4 filter FORWARD 0 -i eno2 -o eno1 -m state --state RELATED,ESTABLISHED -j ACCEPT
```

インターネットからの通信は、送信元IPを限定し10022ポートのみ許可
-------------------------------------------

今回は、public zone を defaultおよびNICを登録してActive化、それに設定を追加していくことにします。

```bash:設定
SOURCE_ADDR="<許可したいアクセス元のIPアドレス>"
# Default Zoneの確認
firewall-cmd --get-default-zone
# publicをDefaultへ
firewall-cmd --set-default-zone=public --permanent
# Active Zoneの確認
firewall-cmd --get-active-zone
# NICを明示的に登録しZoneをActive化
firewall-cmd --change-interface=eno1 --zone=public --permanent
# sshのサービスを削除し、すべてのsshアクセスをdeny
firewall-cmd --remove-service=ssh --zone=public --permanent
# 特定のIPアドレスのみ10022番を開ける
firewall-cmd --add-rich-rule="rule family="ipv4" \
               source address="${SOURCE_ADDR}" \
               port protocol="tcp" port="10022" accept" \
             --zone=public --permanent
# 永続設定の再読み込み
firewall-cmd --reload
```

```bash:確認
firewall-cmd --list-all --zone=public
```

```text:response
public
  target: default
  icmp-block-inversion: no
  interfaces: 
  sources: 
  services: dhcpv6-client
  ports: 6817/tcp 6818/udp 6818/tcp 6817/udp 8443/tcp
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 
        rule family="ipv4" source address="<許可したIPアドレス>" port port="22" protocol="tcp" accept
```

特定のIPのみ22を10022番へポートフォワーディングする
-------------------------------------------------------------

```bash:設定
SOURCE_ADDR="<許可したいアクセス元のIPアドレス>"
# Active Zoneの確認
firewall-cmd --get-active-zone
# ポートフォワーディングは、NICを明示的に登録しZoneをActive化する必要がある
firewall-cmd --change-interface=eno1 --zone=public --permanent
# public zoneのsshのサービスを削除し、すべてのsshアクセスをdeny
firewall-cmd --remove-service=ssh --zone=public --permanent
# 特定のIPからの接続に対しポートフォワーディング設定 10022 を 22番へ
firewall-cmd --add-rich-rule="rule family="ipv4" \
                              source address="${SOURCE_ADDR}" \
                              forward-port port="22" \
                              protocol="tcp" to-port="10022"" \
             --zone=public --permanent 
# 永続設定の再読み込み
firewall-cmd --reload
```

```bash:確認
firewall-cmd --list-all --zone=public
```

```text:response
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eno1
  sources: 
  services: dhcpv6-client
  ports:
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 
        rule family="ipv4" source address="<許可したIPアドレス>" forward-port port="22" protocol="tcp" to-port="10022"
```

Outboundを制御する
--------------------------

### tcpの80番を禁止

```bash:command
firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 1 -m state \
     --state NEW -m tcp -p tcp --dport 80 -j DROP
firewall-cmd --reload
firewall-cmd --direct --get-all-rules
```

### 特定のIPアドレスを禁止する

```bash:command
CIDR=10.20.0.1/24
firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 1 -d ${CIDR} -j DROP
firewall-cmd --reload
firewall-cmd --direct --get-all-rules
```

参考
-----------------

- https://www.nedia.ne.jp/blog/tech/2015/10/13/6031
- https://www.nedia.ne.jp/blog/tech/2015/10/15/6089
- https://eng-entrance.com/linux-centos-firewall
- https://qiita.com/MATO/items/e8ae2b528fe9ddc4c25a
- https://www.server-world.info/query?os=CentOS_7&p=firewalld&f=2
- https://www.labohyt.net/blog/server/post-1129/