Contents
概要
firewalldを設定します。firewalldはLinux OS上で有効なファイアウォールです。実態はnftables(CentOS7まではiptables)のフロントエンドであり、簡易的にファイアウォールを設定できます。
前提条件
OS
CentOS Stream 8を使用します。
SELinux
有効です。無効にする場合はこちらを参照して下さい。
Firewalld
無効です。有効化する場合はこちらを参照して必要な許可設定をして下さい。
その他
firewalldはルーターとして機能させる設定も可能ですが、本稿ではサーバーとして外部からのアクセスを制御することのみを取り上げます。
所感
ファイアウォールを実装すべき箇所
firewalldによらず、一般的なファイアウォール(L3/L4ファイアウォールの話です)はネットワーク上の様々な個所で有効化できます。firewalldのようにサーバーOS上、ルーター上、アプリケーション上等。このため実装しようとすれば、全てのファイアウォールを有効にできる個所に細かくファイアウォールを設定可能ですが、設定管理が煩雑となり、逆に設定ミスの元になりセキュリティの穴が生じる可能性もあります。ファイアウォールを有効にすべき個所は、主にネットワーク設計、または管理する範囲に依存します。具体的な例は別に記載します。
ファイアウォール機能の分離
ファイアウォールはサービスを提供するOS上ではなく、ルーター等のゲートウェイ上で実装するほうが良いです。これはサービスを提供するOSのroot権限が乗っ取られた場合、ファイアウォール設定を自由に変更できるためです。逆にファイアウォールは不特定多数に管理インターフェイスを提供することはまずありません。
マイクロセグメンテーション
サーバー間でL2通信が必要でなければ、/30のセグメントでサーバー毎に隔離し、ファイアウォールは接続するゲートウェイに任せたほうがよいです。高セキュリティが必要なサーバー(DMZのサーバー等)は、ゲートウェイの内側でアクセス先を制限します。このケースではサーバー側でファイアウォールを設定する必要性はあまりなく(サーバー管理者とルーター管理者が別でサーバー管理者が個別にファイアウォールを管理したい場合は必要です)、無効にしても良いかと思います。
本格的にファイアウォールとして使うには・・・
前述の通り、firewalldはnftables(iptables)のフロントエンドとして動作し、簡易的な設定が可能ですが、こういった類のものは例に漏れず細かい設定には向いていません。本格的にファイアウォールとして使用する場合は、nftables(iptables)を学ぶ必要があります。尚、CentOS8からはiptablesからnftablesに変更されていますが、iptablesコマンドも使用可能です。ただし、iptablesコマンドで設定した内容も実際はnftablesの設定に反映されています。nftablesの情報はまだまだ少ないので、現段階ではiptablesコマンドが使えるほうが楽ですね。
設定前に
下記のコマンドでデフォルトで定義されている全てのゾーンを確認できます。使用されているゾーンはactiveの記載があります。
[root@centos ~]# firewall-cmd --list-all-zones block target: %%REJECT%% icmp-block-inversion: no interfaces: sources: services: ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: dmz target: default icmp-block-inversion: no interfaces: sources: services: ssh ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: drop target: DROP icmp-block-inversion: no interfaces: sources: services: ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: external target: default icmp-block-inversion: no interfaces: sources: services: ssh ports: protocols: masquerade: yes forward-ports: source-ports: icmp-blocks: rich rules: home target: default icmp-block-inversion: no interfaces: sources: services: cockpit dhcpv6-client mdns samba-client ssh ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: internal target: default icmp-block-inversion: no interfaces: sources: services: cockpit dhcpv6-client mdns samba-client ssh ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: nm-shared target: ACCEPT icmp-block-inversion: no interfaces: sources: services: dhcp dns ssh ports: protocols: icmp ipv6-icmp masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: rule priority="32767" reject public (active) target: default icmp-block-inversion: no interfaces: ens33 sources: services: cockpit dhcpv6-client http ssh ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: trusted target: ACCEPT icmp-block-inversion: no interfaces: sources: services: ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: work target: default icmp-block-inversion: no interfaces: sources: services: cockpit dhcpv6-client ssh ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
下記のコマンドでデフォルトゾーンを確認できます。CentOS8ではデフォルトでデフォルトゾーンがpublicに設定されています。デフォルトゾーンとは、明示的に設定していない全てのインターフェイスで有効になるゾーンとなり、デフォルトでcockpit、dhcpv6-client、sshの3つのサービスが許可されています。
[root@centos ~]# firewall-cmd --get-default-zone public
下記のコマンドでアクティブゾーンを確認できます。アクティブゾーンは実際に使用されているゾーンでとなり、下記の例ではens33インターフェイスにpublicゾーンが割り当てられていることが確認できます。
[root@centos ~]# firewall-cmd --get-active-zone public interfaces: ens33
設定例
設定例#1 デフォルトゾーンに対するサービス許可
設定例#1はデフォルトゾーンのpublicに公開したいサービスを追加します(コマンドでゾーンを指定しない場合はデフォルトゾーンが対象となります)。これは良くインターネットの記事で見かけます。下記の例ではhttpサービスを追加しています。尚、permanentは設定を永続化させるオプションです。permanentが無い場合、reloadすると設定が消えます(以下同様です)。
[root@centos ~]# firewall-cmd --permanent --add-service=http [root@centos ~]# firewall-cmd --reload
下記のコマンドでhttpサービスが許可されていることを確認できます。記載の通り、cockpit、dhcpv6-client、sshも継続して許可されています。デフォルトで許可されているサービスを削除したい場合は、デフォルトで定義されているゾーンを編集するのではなく、新規にカスタムゾーンを作成するほうがお勧めです(設定例#2を参照)。
[root@centos ~]# firewall-cmd --zone=public --list-all public (active) target: default icmp-block-inversion: no interfaces: ens33 sources: services: cockpit dhcpv6-client http ssh ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
設定例#2 カスタムゾーンの作成
設定例#2は新規にカスタムゾーンを作成して必要なサービスを許可します。下記のコマンドでmyzone(カスタムゾーン)を作成しています。
[root@centos ~]# firewall-cmd --permanent --new-zone=myzone
myzoneでsshとhttpサービスを許可し、reloadします。
[root@centos ~]# firewall-cmd --permanent --zone=myzone --add-service=ssh --add-service=http [root@centos ~]# firewall-cmd --reload
myzoneの内容を確認します。sshとhttpサービスのみ許可されています。
[root@centos ~]# firewall-cmd --zone=myzone --list-all myzone target: default icmp-block-inversion: no interfaces: sources: services: http ssh ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
nmcliでmyzoneをens33インターフェイス(厳密にはプロファイルです。以下同じです。)に割り当て、再読み込みさせます。
[root@centos ~]# nmcli connection modify ens33 connection.zone myzone [root@centos ~]# nmcli connection up ens33
ens33インターフェイスの状態を確認します(出力は抜粋しています)。
[root@centos ~]# nmcli connection show ens33 GENERAL.ZONE: myzone
デフォルトゾーンを確認します。下記の通り、publicであることが確認できます。
[root@centos ~]# firewall-cmd --get-default-zone public
この段階では、明示的にmyzoneを割り当てたens33インターフェイス以外にインターフェイスが存在する場合は、それらのインターフェイスにはpublicが割り当てられます。publicでデフォルトで許可されたサービスがあるため、厳密にアクセス制御を行いたい場合は、デフォルトゾーンをdrop(すべて破棄)にします。これにより新規にインターフェイスを追加しても意図しないアクセスをブロックします。新規インターフェイスに対する許可設定は、myzoneとポリシーが同じであればmyzoneを割り当ててもよく、異なるのであれば別のゾーンを作成して割り当てます。
[root@centos ~]# firewall-cmd --set-default-zone=drop [root@centos ~]# firewall-cmd --reload
デフォルトゾーンがdropに変更されたことが確認できます。
[root@centos ~]# firewall-cmd --get-default-zone drop
設定例#3 送信元アドレスの制限
設定例#3は設定例#2をベースとして送信元アドレスを制限します。下記の例では送信元アドレスを10.0.0.0/24に制限します。
[root@centos ~]# firewall-cmd --permanent --zone=myzone --add-source=10.0.0.0/24 [root@centos ~]# firewall-cmd --reload
myzoneの内容を確認します。sourcesに10.0.0.0/24が割り当てられていることが確認できます。この例では、10.0.0.0/24からsshとhttpサービスへのアクセスが許可されます。つまりsshは特定のネットワークからのみ、httpは全て許可という設定はできず、少々柔軟性に欠けます。用途ごとにインターフェイスを分けているケースでは違和感なく使えると思います。より柔軟に設定する場合はrich-ruleを使用します(設定例#4)。
[root@centos ~]# firewall-cmd --zone=myzone --list-all myzone target: default icmp-block-inversion: no interfaces: sources: 10.0.0.0/24 services: http ssh ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
設定例#4 送信元アドレスとサービス制限
設定例#4は設定例#2をベースとしてsshは特定のネットワークから許可、httpは全て許可とします。まず、rich-ruleで送信元アドレスが10.0.0.0/24からのsshを許可します。
[root@centos ~]# firewall-cmd --permanent --zone=myzone --add-rich-rule='rule family="ipv4" source address="10.0.0.0/24" service name=ssh accept' [root@centos ~]# firewall-cmd --reload
次に定義済みのsshサービス許可を削除します。
[root@centos ~]# firewall-cmd --permanent --zone=myzone --remove-service=ssh [root@centos ~]# firewall-cmd --reload
myzoneの内容を確認します。rich-ruleで送信元アドレスが10.0.0.0/24からのsshが許可され、基本的な設定(rich-rule以外の設定)で全ての送信元アドレスからhttpが許可されています(rich-ruleは基本的な設定と独立しています)。また、基本的な設定では送信元アドレスしか制限できませんが、rich-ruleでは宛先アドレスも制限可能です。
[root@centos ~]# firewall-cmd --zone=myzone --list-all myzone target: default icmp-block-inversion: no interfaces: sources: services: http ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: rule family="ipv4" source address="10.0.0.0/24" service name="ssh" accept
設定例#5 ポート番号での制限
設定例#5はserviceに存在しないサービスをポート番号で許可します。設定例#4をベースとします。firewalldのserviceは/usr/lib/firewalld/services内にサービス毎に定義されており、ここに存在するサービス以外はfirewalldのserviceコマンドで使用できず(個別にカスタムサービスを作成可能ですが割愛します)、ポート番号での許可が必要です。下記の例ではtcp:12345を許可しています。udpの場合は単にtcpをudpに置き換えます。
[root@centos ~]# firewall-cmd --permanent --zone=myzone --add-port=12345/tcp [root@centos ~]# firewall-cmd --reload
rich-ruleで使用する場合も同様です。ポート番号だけ変えて許可しています。
[root@centos ~]# firewall-cmd --permanent --zone=myzone --add-rich-rule='rule family="ipv4" source address="10.0.0.0/24" port port=12346 protocol=tcp accept' [root@centos ~]# firewall-cmd --reload
myzoneの内容を確認します。
[root@centos ~]# firewall-cmd --zone=myzone --list-all myzone target: default icmp-block-inversion: no interfaces: sources: services: http ports: 12345/tcp protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: rule family="ipv4" source address="10.0.0.0/24" service name="ssh" accept rule family="ipv4" source address="10.0.0.0/24" port port="12346" protocol="tcp" accept
その他
firewalldを無効化する場合
firewalldは他のサービスを同様、systemdで管理されていますので下記のコマンドで停止できます。
[root@centos ~]# systemctl disable --now firewalld.service