Cent OS 7 の話です。firewalld がなかなかの難物で、ネットで探してもピタリと来る情報がないので、色々と実験をしていました。実際は、かなりシンプルな代物ですが、“ゾーン” の概念の説明が要領を得ず、さっぱり分からないという人が多いのではないかと思います。

基本編では、ゾーンを理解するために、簡単な例題を使って説明します。

お題:

  • デフォルトのゾーン public で、ssh, http, https, dhcpv6-client が割り当て済み
  • 国内からのアクセスだけを許すゾーン domestic を作成し、そこに ssh を割り当てる

ssh にログインを試みる不逞の輩が後を絶たないので、そいつらをまとめてブロックしておきたい、というよくある話です。このようなファイアーウォールを、ゾーンを使って構築します。

新しいゾーン domestic を作成します。サーバを再起動した際に、設定が維持されるように --permanent を付けます(以下同じ)。

$ sudo firewall-cmd --permanent --new-zone=domestic
success
$ 

ゾーン domestic に許可したいアドレス(ここでは例として 192.168.1.0/24 )を割り当てます。

$ sudo firewall-cmd --permanent --zone=domestic --add-source=192.168.1.0/24
success
$ 

実験なので、一つだけ割り当てます。日本国内に割り当てられているアドレスについて、これを繰り返せば OK ですが、この段階でそれをやるのは大変ですし、実際にはパフォーマンスの問題を引き起こすので、別の方法を採ります。ここでは、ゾーンを使ってホワイトリスト形式のアクセス制御ができると理解することが目的なので、一つだけやれば十分です。

ゾーン domesticssh サービスを割り当てます。そして、public からは ssh サービスを削除します。

$ sudo firewall-cmd --permanent --zone=domestic --add-service=ssh
success
$ sudo firewall-cmd --permanent --zone=public --remove-service=ssh
success
$ 

ここまでの設定を反映し、各ゾーンの設定を確認します。

$ sudo firewall-cmd --reload
success
$ sudo firewall-cmd --list-all-zones
...
domestic (active)
  target: default
  icmp-block-inversion: no
  interfaces: 
  sources: 192.168.1.0/24
  services: ssh
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  sourceports: 
  icmp-blocks: 
  rich rules: 
	
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources: 
  services: dhcpv6-client http https
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  sourceports: 
  icmp-blocks: 
  rich rules: 
	
...

ここでは domesticpublic だけを抜粋して記載しています。この 2つが active なゾーンで、他のゾーンは(特に設定をいじってなければ) active ではありません。これで ssh のパケットは、sources のアドレスからのみ受け付け、httphttps は特に制限を設けずに受け付けるようになりました。

このように設定すると、お題のような、ssh は国内限定、他のサービスは全世界に公開というものが実現できるとご理解いただけると思います。

ゾーンは、sources 等によって振り分けられるというところがポイントです。同じようなことをするのに rich rules を使う方法を紹介している人もいらっしゃいますが、実際にはゾーンだけでシンプルに実現できます。

長くなったので、一旦終わります。firewalld の設定(実際編) では、ipset を使って一気に設定する方法を紹介しています。