firewalld の target の default と REJECT の違い

firewalld でインタフェースやソースアドレスに基づいて特定のゾーンに入ったパケットが、そのゾーンに設定されているサービスやポートにマッチしなかったときのデフォルトの動作は、ゾーンの target で指定します。

指定します、と言っても定義済のゾーンでは次のように定義されています。これを変更することはあまりないと思います。

zone target
drop DROP
trusted ACCEPT
block %%REJECT%%
他のゾーン default

ACCEPT はパケットを許可、DROP はパケットをドロップします。

%%REJECT%%(以下 REJECT と記述します)と default は、どちらも ICMP destination unreachable かなにかで拒否を応答しますが、以下の記述だけを見ると REJECTdefault に違いは無いように思えます。

The %%REJECT%% target is used in block zone to reject (with default firewalld reject type) every packet not matching any rule.

https://firewalld.org/documentation/zone/options.html

がしかし、実際には下記の issue で説明されているような違いがあります。

https://github.com/firewalld/firewalld/issues/590

要約すると、

  1. default は icmp が通る
    • REJECT は icmp は明示的に通さない限り通らない
  2. A -> B な forward で A のゾーンが default なら B のゾーンも適用される
    • A のゾーンが REJECT なら B は適用されずに Reject される
  3. AllowZoneDrifting が有効なら)ソースアドレスベースのゾーンで default になれば、インタフェースベースのゾーンも続けて適用される
    • ソースベースのゾーンで REJECT になれが、インタフェースベースのゾーンは適用されずに Reject される

最後の AllowZoneDrifting について、以下によると元々はこれがデフォの動きだったのですが、

https://firewalld.org/2020/01/allowzonedrifting

0.6.5/0.7.0/0.8.0 でこれはバグ扱いで無効になりました。ゾーンベースの FW ではパケットが複数のゾーンを通るべきではないためらしいです。その後、0.7.4/0.8.2/1.0.0 で AllowZoneDrifting でオプショナルな機能になりました(デフォは無効)。