ITエンジニアのコツコツ日記

ITエンジニアの雑記です

Firewalldの初期設定をiptablesから読み解いてみる

Firewalldとは

f:id:itkotsukotsu:20201010172106p:plain:w400

FirewalldはRedhat Enterprise Linux 7 (RHEL7)系から主流となったパケットフィルタツールだ。

firewalldはiptablesを経由してLinuxカーネルのNetfilterを操作するフロントエンドツールであるため、firewalldがどのようなiptables設定を施すか把握すると良い。

iptablesの使い方についてこの記事を読んでほしい。

Firewalld有効時のiptables

firewalldのサービスが停止した状態のiptablesは以下。

チェインとしてINPUT, OUTPUT, FORWARDがあり、特に何もエントリが無い。

[root@localhost ~]# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

ここでfirewalldを有効にする。

firewalldの設定は以下で標準設定のままだ。

なお、NICは3つありens160, ens192, ens224がある。

[root@localhost ~]# firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no        
  interfaces: ens160 ens192 ens224
  sources:
  services: dhcpv6-client ssh     
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

firewalldのサービス有効時のiptablesは以下。 非常にチェインとエントリが多い。

[root@localhost ~]# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED     
ACCEPT     all  --  anywhere             anywhere
INPUT_direct  all  --  anywhere             anywhere
INPUT_ZONES_SOURCE  all  --  anywhere             anywhere
INPUT_ZONES  all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere             ctstate INVALID
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED     
ACCEPT     all  --  anywhere             anywhere
FORWARD_direct  all  --  anywhere             anywhere
FORWARD_IN_ZONES_SOURCE  all  --  anywhere             anywhere
FORWARD_IN_ZONES  all  --  anywhere             anywhere
FORWARD_OUT_ZONES_SOURCE  all  --  anywhere             anywhere
FORWARD_OUT_ZONES  all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere             ctstate INVALID
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere
OUTPUT_direct  all  --  anywhere             anywhere

Chain FORWARD_IN_ZONES (1 references)
target     prot opt source               destination
FWDI_public  all  --  anywhere             anywhere            [goto]
FWDI_public  all  --  anywhere             anywhere            [goto]
FWDI_public  all  --  anywhere             anywhere            [goto]
FWDI_public  all  --  anywhere             anywhere            [goto]

Chain FORWARD_IN_ZONES_SOURCE (1 references)
target     prot opt source               destination

Chain FORWARD_OUT_ZONES (1 references)
target     prot opt source               destination
FWDO_public  all  --  anywhere             anywhere            [goto]
FWDO_public  all  --  anywhere             anywhere            [goto]
FWDO_public  all  --  anywhere             anywhere            [goto]
FWDO_public  all  --  anywhere             anywhere            [goto]

Chain FORWARD_OUT_ZONES_SOURCE (1 references)
target     prot opt source               destination

Chain FORWARD_direct (1 references)
target     prot opt source               destination

Chain FWDI_public (4 references)
target     prot opt source               destination
FWDI_public_log  all  --  anywhere             anywhere
FWDI_public_deny  all  --  anywhere             anywhere
FWDI_public_allow  all  --  anywhere             anywhere
ACCEPT     icmp --  anywhere             anywhere

Chain FWDI_public_allow (1 references)
target     prot opt source               destination

Chain FWDI_public_deny (1 references)
target     prot opt source               destination

Chain FWDI_public_log (1 references)
target     prot opt source               destination

Chain FWDO_public (4 references)
target     prot opt source               destination
FWDO_public_log  all  --  anywhere             anywhere
FWDO_public_deny  all  --  anywhere             anywhere
FWDO_public_allow  all  --  anywhere             anywhere

Chain FWDO_public_allow (1 references)
target     prot opt source               destination

Chain FWDO_public_deny (1 references)
target     prot opt source               destination

Chain FWDO_public_log (1 references)
target     prot opt source               destination

Chain INPUT_ZONES (1 references)
target     prot opt source               destination
IN_public  all  --  anywhere             anywhere            [goto]
IN_public  all  --  anywhere             anywhere            [goto]
IN_public  all  --  anywhere             anywhere            [goto]
IN_public  all  --  anywhere             anywhere            [goto]

Chain INPUT_ZONES_SOURCE (1 references)
target     prot opt source               destination

Chain INPUT_direct (1 references)
target     prot opt source               destination

Chain IN_public (4 references)
target     prot opt source               destination
IN_public_log  all  --  anywhere             anywhere
IN_public_deny  all  --  anywhere             anywhere
IN_public_allow  all  --  anywhere             anywhere
ACCEPT     icmp --  anywhere             anywhere

Chain IN_public_allow (1 references)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:ssh ctstate NEW,UNTRACKED

Chain IN_public_deny (1 references)
target     prot opt source               destination

Chain IN_public_log (1 references)
target     prot opt source               destination

Chain OUTPUT_direct (1 references)
target     prot opt source               destination

一つ一つ読み解いていこう。

Firewalldのチェイン

Firewalld有効時のiptablesのチェイン一覧は以下だ。

[root@localhost ~]# iptables -L -n --line-number | grep Chain
Chain INPUT (policy ACCEPT)
Chain FORWARD (policy ACCEPT)
Chain OUTPUT (policy ACCEPT)
Chain FORWARD_IN_ZONES (1 references)
Chain FORWARD_IN_ZONES_SOURCE (1 references)
Chain FORWARD_OUT_ZONES (1 references)
Chain FORWARD_OUT_ZONES_SOURCE (1 references)
Chain FORWARD_direct (1 references)
Chain FWDI_public (4 references)
Chain FWDI_public_allow (1 references)
Chain FWDI_public_deny (1 references)
Chain FWDI_public_log (1 references)
Chain FWDO_public (4 references)
Chain FWDO_public_allow (1 references)
Chain FWDO_public_deny (1 references)
Chain FWDO_public_log (1 references)
Chain INPUT_ZONES (1 references)
Chain INPUT_ZONES_SOURCE (1 references)
Chain INPUT_direct (1 references)
Chain IN_public (4 references)
Chain IN_public_allow (1 references)
Chain IN_public_deny (1 references)
Chain IN_public_log (1 references)
Chain OUTPUT_direct (1 references)

ビルドインチェインとなるINPUT, FORWARD, OUTPUTがあり、それ以降はユーザ定義チェインとなる。

非常に多くのユーザ定義チェインがあり、Firewalldの設計思想に合わせたエントリの分類ができるようになっている。

ビルドインチェイン

ビルドインチェインの例としてINPUTを見てみよう。

Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED     
ACCEPT     all  --  anywhere             anywhere
INPUT_direct  all  --  anywhere             anywhere
INPUT_ZONES_SOURCE  all  --  anywhere             anywhere
INPUT_ZONES  all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere             ctstate INVALID
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

ACCEPTですべての通信を許可するエントリがあり、そのあとにtargetがINPUT_direct, INPUT_ZONES_SOURCE, INPUT_ZONESがある。

これらはユーザ定義チェインであり、ビルドインチェインであるINPUTにエントリがあり、呼び出される。

Firewalldにはゾーンの考え方があり、ゾーン毎にチェインを作成している。

各ユーザ定義チェインの呼び出し順はビルドインチェインのこのINPUTを見ればわかる。

ユーザ定義チェイン

Firewalldはユーザ定義チェインを作成し、ビルドインチェインにエントリを追加してFirewalldの設定を施している。

例として、INTPUTチェインに含まれるINPUT_directを見てみよう。

Chain INPUT_direct (1 references)
target     prot opt source               destination

1 referencesとなっており、参照をもつユーザ定義チェインであることが分かる。

特にエントリはないがfirewalld が作成するINPUT_directに分類するエントリが定義される。

Firewalldの初期設定の動き

ビルドインチェインエントリのユーザ定義チェインの動きを追って、Firewalldの設定を読み解いてみる。

Firewalld上の設定

Firewalld上の設定は以下だ。(※再掲)

  • target: defaultで基本動作はREJECT(DROP)
  • 3つのインターフェース(NIC)向けに設定
  • icmpは許可(ping通信等)
  • ssh許可
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens160 ens192 ens224
  sources:
  services: dhcpv6-client ssh
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

iptables上の設定

このFirewalldの動きを実現するiptablesの記述がされていれば良いことになる。 それぞれ該当するものがあるか確認する。

パケットのデフォルト動作は破棄

Chain INPUT (policy ACCEPT)
...
...
DROP       all  --  anywhere             anywhere             ctstate INVALID
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

INPUTチェインにDROPREJECTのエントリがある。

REJECTはICMPのエラーを返すようにしている。

これらのエントリでINPUTのACCEPTに受理されなかったのは破棄される。

3つのインターフェース(NIC)向けに設定

ユーザ定義チェインに インタフェースオプションを指定して各NICに対して設定が適用されるようになっていることが読み取れる。

# iptables --list-rules
...
...
-A FORWARD_IN_ZONES -i ens224 -g FWDI_public
-A FORWARD_IN_ZONES -i ens192 -g FWDI_public
-A FORWARD_IN_ZONES -i ens160 -g FWDI_public
-A FORWARD_IN_ZONES -g FWDI_public
Chain FORWARD_IN_ZONES (1 references)
target     prot opt source               destination
FWDI_public  all  --  anywhere             anywhere            [goto]
Chain FWDI_public (4 references)   ←3NIC分追加されている
target     prot opt source               destination
FWDI_public_log  all  --  anywhere             anywhere
FWDI_public_deny  all  --  anywhere             anywhere
FWDI_public_allow  all  --  anywhere             anywhere
ACCEPT     icmp --  anywhere             anywhere

icmpは許可(ping通信等)

NICが参照するチェインFWDI_publicにてACCEPT icmpが記述されている。

Chain FWDI_public (4 references)
target     prot opt source               destination
FWDI_public_log  all  --  anywhere             anywhere
FWDI_public_deny  all  --  anywhere             anywhere
FWDI_public_allow  all  --  anywhere             anywhere
ACCEPT     icmp --  anywhere             anywhere

ssh許可

ユーザ定義チェインのIN_public_allowtcp dpt:sshが許可されている。

Chain IN_public_allow (1 references)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:ssh ctstate NEW,UNTRACKED

まとめ

firewalldはzone管理等やりたい設定をするには使いやすいフロントエンドのパケットフィルタツールだ。

しかし実態としてはiptablesを操作しており、firewalldで実現したいiptablesの設定がされている。

Dockerやkubnerenes等はiptablesを操作して内部仮想ネットワークを構築しており、多数のツールによってiptablesが設定されるため想定外の動きをする時がある。

疎通が取れない等で問題を切り分けするならiprablesを読み解くのが一番正確だろう。