CentOS7にてコマンドでファイアウォールをいじる(firewall-cmd)

CentOS7で穴開けるときに毎回ど忘れするので。

# チートシート
- 全般
  - `firewall-cmd --reload` *(設定の反映)*
- ゾーン
  - `firewall-cmd --list-all-zone | grep "^\w"` *(全ゾーン名の確認)*
  - `firewall-cmd --info-zone <ゾーン名>` *(ゾーンの詳細確認)*　
  - `firewall-cmd --permanent --new-zone=<ゾーン名>` *(独自ゾーンの作成)*
- ポート
  - `firewall-cmd --permanent --zone=<zone名> --add-port=<ポート番号>/<プロトコル>` *(ポートの追加)*
  - `firewall-cmd --permanent --zone=<zone名> --remove-port=<ポート番号>/<プロトコル>` *(ポートの削除)*
- サービス
  - `firewall-cmd --get-services` *(全サービスの確認)*
  - `firewall-cmd --info-service <サービス名>` *(サービスの詳細確認)*
  - `firewall-cmd --permanent --new-service=<サービス名>` *(サービスの追加)*
  - `firewall-cmd --permanent --service=<サービス名> --add-port=<ポート番号>/<プロトコル>` *(サービスへのポートの追加)*
  - `firewall-cmd --permanent --zone=<ゾーン名> --add-service=<サービス名>` *(ゾーンへのサービスの追加)*
- インタフェース
  - `firewall-cmd --permanent --zone=<ゾーン名> --add-interface=<インタフェース名>` *(インタフェースの割り当て変更)*

# firewalldって何ですか
[ここ](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/security_guide/sec-using_firewalls)見て頂ければわかりますが、従来のiptablesサービスに代わりパケットフィルタリングを司る、新しいデーモンです。
とは言え、リンク先の図4.1を見る限りではiptablesコマンドを実行しているようですね。

# ネットワークゾーンって何ですか
firewalldにおいて、各ネットワークインタフェース(以下、I/F)はネットワークゾーン(以下、ゾーン)に所属します。
そして、そのI/Fにおける通信は、所属するゾーンに設定されたルールのもと、フィルタリングが実施されます。
ゾーン=仮想的なファイアウォールと捉えてもよいと思います。

![Untitled Diagram (3).png](https://qiita-image-store.s3.amazonaws.com/0/161568/54db5847-189f-91b2-4729-523c8f380fad.png)



CentOS7においては、以下のゾーンがあらかじめ用意されており、I/Fはデフォルトでpublicに所属します。(デフォルトのゾーンを変更することは可能)
「active」というのは、いずれかのI/Fがそのゾーンに登録されていることを意味します。

```
# firewall-cmd --list-all-zone | grep "^\w"
work
drop
internal
external
trusted
home
dmz
public (active)
block
```

尚、独自のゾーンを作ることも可能です。

```
# firewall-cmd --permanent --new-zone=babaa_zone
success
# firewall-cmd --reload
success
# firewall-cmd --info-zone babaa_zone
babaa_zone
  target: default
  icmp-block-inversion: no
  interfaces: 
  sources: 
  services: 
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  sourceports: 
  icmp-blocks: 
  rich rules: 
 
```

# ゾーンの設定をする
せっかくなので先ほど作成したbabaa_zoneを設定していきます。
設定するにあたり、コマンドに`--permanent`オプションを指定すると、再起動等をしても消えない、恒久的な設定になります。
但し、`--permanent`オプションでの設定は即時反映されないため、`firewall-cmd --reload`を実行して反映してやる必要があります。

```
# firewall-cmd --permanent --zone=babaa_zone --add-port=5555/udp
success
# firewall-cmd --info-zone babaa_zone | grep " ports"
  ports: 
# firewall-cmd --reload
success
# firewall-cmd --info-zone babaa_zone | grep " ports"
  ports: 5555/udp
```


## ポート開放
ポート開閉は`--add-port`、`--remove-port`で実施可能です。

```
# firewall-cmd --zone=babaa_zone --add-port=5555/udp
# firewall-cmd --info-zone babaa_zone | grep " ports"
  ports: 5555/udp
# firewall-cmd --zone=babaa_zone --remove-port=5555/udp
success
# firewall-cmd --info-zone babaa_zone | grep " ports"
  ports: 
```

また、firewalldでは、ポート開放の際、ポート番号を直接指定するほかに、サービスを指定することもできます。
サービスは、プロトコルやポートの情報に名前を付けたものと考えてください。
例えば、tcp/80であれば、httpというサービス名です。

サービスをゾーンに対して登録してやれば、そのサービスに紐づくポートが開放されます。

```
# firewall-cmd --zone=babaa_zone --add-service=https
success
# firewall-cmd --info-zone babaa_zone | grep ser
  services: https
```

どんなサービスがあるかは、`firewall-cmd --get-services`で確認できます。
また、設定は`--info-service`で確認できます。

```
# firewall-cmd --info-service https
https
  ports: 443/tcp
  protocols: 
  source-ports: 
  modules: 
  destination: 
```

あるいはファイルを直接確認でもよいと思います。

```
# cat /usr/lib/firewalld/services/https.xml
<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>Secure WWW (HTTPS)</short>
  <description>HTTPS is a modified HTTP used to serve Web pages when security is important. Examples are sites that require logins like stores or web mail. This option is not required for viewing pages locally or developing Web pages. You need the httpd package installed for this option to be useful.</description>
  <port protocol="tcp" port="443"/>
</service>
```

また、独自のサービスを追加することもできます。
例えば、minidlnaは1900/udpと8200/tcpが必要なので、以下のような感じで登録します。

```
# firewall-cmd --permanent --new-service=minidlna
success
# firewall-cmd --permanent --service=minidlna --add-port=8200/tcp
success
# firewall-cmd --permanent --service=minidlna --add-port=1900/udp
success
# firewall-cmd --reload
success
# firewall-cmd --info-service minidlna
minidlna
  ports: 1900/udp 8200/tcp
  protocols: 
  source-ports: 
  modules: 
  destination: 
# cat /etc/firewalld/services/minidlna.xml
<?xml version="1.0" encoding="utf-8"?>
<service>
  <port protocol="udp" port="1900"/>
  <port protocol="tcp" port="8200"/>
</service>
```

permanentつけ忘れ対策として、設定ファイルの確認は必ずセットで行っておきたいところです。

## 細かい設定
とは言え、この程度の設定では企業のようなネットワークでのフィルタリングには不十分です。
ということで、firewalldは`--add-rich-rule`でより細かいルール設定ができるようになっています。([この辺](https://fedoraproject.org/wiki/Features/FirewalldRichLanguage#Handle_rich_rules_with_the_command_line_client)ご参考)
以下は、192.168.1のセグメントからのminidlnaへの接続を許可する設定となります。

```
# firewall-cmd --permanent --zone=babaa_zone --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" service name="minidlna"
 accept'
success
# firewall-cmd --reload
success
# firewall-cmd --info-zone babaa_zone 
babaa_zone
  target: default
  icmp-block-inversion: no
  interfaces: 
  sources: 
  services: softether ssh_custom
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  sourceports: 
  icmp-blocks: 
  rich rules: 
        rule family="ipv4" source address="192.168.1.0/24" service name="minidlna" accept
```

更に細かいものとして、`--direct`というオプションもあります。
これを利用すれば従前のiptablesコマンド並の設定が行えるようです。
(CentOS7でそこまでの必要性に迫られたことがないので、未実施です…すみません)

# ゾーンにI/Fを割り当てる
ゾーンの設定があらかた完了したので、I/Fを割り当てます。

```
# firewall-cmd --permanent --zone=babaa_zone --add-interface=enp38s0
The interface is under control of NetworkManager, setting zone to 'babaa_zone'.
success
# firewall-cmd --info-zone babaa_zone
babaa_zone (active)
  target: default
  icmp-block-inversion: no
  interfaces: enp38s0
  sources: 
  services: softether ssh_custom
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  sourceports: 
  icmp-blocks: 
  rich rules: 
        rule family="ipv4" source address="192.168.1.0/24" service name="minidlna" accept
```

無事割り当て完了です。
尚、この操作をした時にpublic→babaa_zoneへの変更が発生したわけですが、特にターミナルの接続断は発生しませんでした。
また、このコマンドはreloadせずとも即時に反映されました。

# デフォルトゾーンの変更
取りあえず問題なさそうなので、デフォルトのゾーンを作成したゾーンにしてしまいます。

```

```

---
以上でする。