Edited at

CentOS7のfirewalldをまじめに使うはじめの一歩(systemdも少し)

More than 3 years have passed since last update.


基本


デフォルト設定ファイルとユーザー設定ファイルの関係

/usr/lib下のsystemdないしfirewalldにデフォルト設定ファイルがあるので、設定を変更する場合は該当するファイルを同じディレクトリ構成で/etcに置く。

例えばsystem/default.targetというファイルの場合、/usr/libでのgraphical.targetへのシンボリックリンクが、/etcmulti-user.targetへのシンボリックリンクで上書きされているのがわかる。

[root@localhost ~]# ls -l /usr/lib/systemd/system/default.target

lrwxrwxrwx. 1 root root 16 Oct 21 14:26 /usr/lib/systemd/system/default.target -> graphical.target
[root@localhost ~]# ls -l /etc/systemd/system/default.target
lrwxrwxrwx. 1 root root 37 Jul 22 03:38 /etc/systemd/system/default.target -> /lib/systemd/system/multi-user.target

firewalldの設定についても同様で、etcの下にあるzones/public.xml/usr/lib下のデフォルト設定を上書きしている。

[root@localhost ~]# ls -l /etc/firewalld/zones/public.xml

-rw-r--r--. 1 root root 340 Oct 21 15:32 /etc/firewalld/zones/public.xml
[root@localhost ~]# ls -l /usr/lib/firewalld/zones/public.xml
-rw-r-----. 1 root root 315 Jun 10 07:19 /usr/lib/firewalld/zones/public.xml


NICの確認

ip lでリンク、ip aでアドレス、ip rでルーティング。

[root@localhost ~]# ip l

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
link/ether 08:00:27:20:5d:4b brd ff:ff:ff:ff:ff:ff
[root@localhost ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
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: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:20:5d:4b brd ff:ff:ff:ff:ff:ff
inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic enp0s3
valid_lft 82486sec preferred_lft 82486sec
inet6 fe80::a00:27ff:fe20:5d4b/64 scope link
valid_lft forever preferred_lft forever
[root@localhost ~]# ip r
default via 10.0.2.2 dev enp0s3 proto static metric 1024
10.0.2.0/24 dev enp0s3 proto kernel scope link src 10.0.2.15


参考


ケーススタディ1: http通信を許可する

6までならiptablesで操作していたもの。nginxは別途インストール済という前提で。

systemctl status firewalldfirewalldが動いてるか調べて、動いてなかったらsystemctl start firewalldで起動。


現状のゾーン設定を調べる firewall-cmd --list-all

firewalldではゾーンという単位で設定が定義され、ゾーンとNICが紐づくことで設定が有効になる。

[root@localhost ~]# firewall-cmd --list-all

public (default, active)
interfaces: enp0s3
sources:
services: dhcpv6-client ssh
ports:
masquerade: no
forward-ports:
icmp-blocks:
rich rules:

上記のipコマンドででてきた、enp0s3インタフェースに紐付いていることがわかる。


すべてのゾーンの情報をみる firewall-cmd --list-all-zones

[root@localhost ~]# firewall-cmd --list-all-zones

block
interfaces:
sources:
...
dmz
interfaces:
...
drop
interfaces:
sources:
...
work
interfaces:
sources:
...


ゾーンに設定されているサービスを確認する: firewall-cmd --list-services --zone=public --permanent

--permanentについては後述。

[root@localhost ~]# firewall-cmd --list-services --zone=public  --permanent

dhcpv6-client ssh


追加できるサービスを確認する: firewall-cmd --get-services

[root@localhost ~]# firewall-cmd --get-services

amanda-client bacula bacula-client dhcp dhcpv6 dhcpv6-client dns ftp high-availability http https imaps ipp ipp-client ipsec kerberos kpasswd ldap ldaps libvirt libvirt-tls mdns mountd ms-wbt mysql nf
s ntp openvpn pmcd pmproxy pmwebapi pmwebapis pop3s postgresql proxy-dhcp radius rpc-bind samba samba-client smtp ssh telnet tftp tftp-client transmission-client vnc-server wbem-https

各サービスの詳細は設定ファイルをみるのがよいと思う。変更したい場合は上記の通り、/etc/firewalldにコピーして行う。

[root@localhost ~]# cat /usr/lib/firewalld/services/http.xml 

<?xml version="1.0" encoding="utf-8"?>
<service>
<short>WWW (HTTP)</short>
<description>HTTP is the protocol used to serve Web pages. If you plan to make your Web server publicly available, enable this option. This option is not required for viewing pages locally or developing Web pages.</description>
<port protocol="tcp" port="80"/>
</service>


ゾーンにサービスを追加する: firewall-cmd --add-service=http --zone=public --permanent

--permanentをつけないと設定ファイルが更新されないので、サービスをreloadすると元の状態に戻ってしまう。

[root@localhost ~]# firewall-cmd --add-service=http --zone=public --permanent

success

確認。

[root@localhost ~]# firewall-cmd --list-services --zone=public  --permanent

dhcpv6-client http ssh

追加できました。

実際のファイルをみても、/usr/lib/firewalld/zones/public.xmlは変更されてなくて、

[root@localhost ~]# cat /usr/lib/firewalld/zones/public.xml

<?xml version="1.0" encoding="utf-8"?>
<zone>
<short>Public</short>
<description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
<service name="ssh"/>
<service name="dhcpv6-client"/>
</zone>

/etc/firewalld/zones/public.xmlが更新されてます。

[root@localhost ~]# cat /etc/firewalld/zones/public.xml

<?xml version="1.0" encoding="utf-8"?>
<zone>
<short>Public</short>
<description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
<service name="dhcpv6-client"/>
<service name="http"/>
<service name="ssh"/>
</zone>

これで、外部から80ポートへアクセスできるようになりました。サービスの再起動も不要でした。


ケーススタディ2: 特定ポートのhttp通信を許可する

例として5000ポートでの通信を許可する場合。

5000ポートを使う適当なプロセスをでっちあげる。

[root@localhost ~]# python -m SimpleHTTPServer 5000

Serving HTTP on 0.0.0.0 port 5000 ...

/usr/lib/firewalld/services/http.xml/etc/firewalld/servicesにコピーして編集。

[root@localhost ~]# cp /usr/lib/firewalld/services/http.xml /etc/firewalld/services/

[root@localhost ~]# vi /etc/firewalld/services/http.xml

みればわかるくらい単純だけどこんな感じに。

<?xml version="1.0" encoding="utf-8"?>

<service>
<short>WWW (HTTP)</short>
<description>HTTP is the protocol used to serve Web pages. If you plan to make your Web server publicly available, enable this option. This option is not required for viewing pages locally or developing Web pages.</description>
<port protocol="tcp" port="80"/>
<port protocol="tcp" port="5000"/>
</service>

httpサービスは追加済なのでreloadする。

[root@localhost ~]# firewall-cmd --reload

以上で完了。

設定の書き方はman firewalld.serviceみる。


ケーススタディ3: 独自のサービスを追加して管理する

上記では既存のhttpサービスに追加したけど、たぶん、独自のサービスを追加したほうが管理もしやすいので正道なはず。

編集したファイルは不要なので削除。リロードもしておく。

[root@localhost ~]# rm /etc/firewalld/services/http.xml

[root@localhost ~]# firewall-cmd --reload

既存のhttpファイルをもとにpy-appという独自サービスの設定ファイルを作成。

firewall-cmd --new-service=[service] --permanentの使い方がいまいちわからないので今回はファイルを直接作成する。

[root@localhost ~]# cp /usr/lib/firewalld/services/http.xml /etc/firewalld/services/py-app.xml

中身は以下。

<?xml version="1.0" encoding="utf-8"?>

<service>
<short>myapp by python</short>
<description>for file sharing</description>
<port protocol="tcp" port="5000"/>
</service>

作成できたらサービスとして追加できるが、--get-servicesには表示されないので、firewall-cmd --reloadしたほうがいいとは思う。いずれにせよ、ファイルが作成できた時点で以下のコマンドは実行可能。

[root@localhost ~]# firewall-cmd --add-service=py-app --zone=public --permanent                                                                                                                         

success
[root@localhost ~]# firewall-cmd --list-services --zone=public --permanent
dhcpv6-client http py-app ssh

今回はreloadしないと反映できなかった。さっきのケースが勘違いかも。

[root@localhost ~]# firewall-cmd --reload

おそらくこんな感じでPostgresqlやらrabbitmqやらfluentdやらのサービスを作成していくことになるんだろう。


ケーススタディ4: firewalldの設定を一覧でみる

firewalldはD-BUS経由での操作もできる単なる管理インタフェースみたいなので、実際のフィルタリングはiptablesが動いている。なので、設定を一覧でみたい、実際の反映結果をみたい、というときは今までどおり、iptables-saveを使えばいい。

[root@localhost ~]# iptables-save 

# Generated by iptables-save v1.4.21 on Tue Oct 21 18:04:25 2014
*nat
:PREROUTING ACCEPT [4:176]
:INPUT ACCEPT [4:176]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
...
-A INPUT_ZONES -i enp0s3 -g IN_public
-A INPUT_ZONES -g IN_public
-A IN_public -j IN_public_log
-A IN_public -j IN_public_deny
-A IN_public -j IN_public_allow
-A IN_public_allow -p tcp -m tcp --dport 80 -m conntrack --ctstate NEW -j ACCEPT
-A IN_public_allow -p tcp -m tcp --dport 5000 -m conntrack --ctstate NEW -j ACCEPT
-A IN_public_allow -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
COMMIT
# Completed on Tue Oct 21 18:04:25 2014

というわけで簡単なことを筋道立てて設定・管理するならfirewalldが便利なんだろう。あとD-BUSから操作する場合。

けど、複雑なことをエイヤッと解決したい場合は今までどおりiptablesを直接触ったほうがいいと思う。


追記: firewalldとiptablesの設定の共有はできないっぽい

などを読むと、firewalld/etc/sysconfig/iptablesの設定を読んでくれないっぽい。なのでどちらを使うか選ぶしかないっぽい。

firewalldの代わりにiptablesを有効にする際のざっくり手順は以下。

yum install iptables-services

systemctl stop firewalld
systemctl disable firewalld
systemctl enable iptables
systemctl start iptables