Linux マシンがネットワーク内に配置されていれば、カーネルの機能を利用してネットワークパケットの制御を行い、内部ネットワークと外部ネットワークを区別して扱ったり、パケットそのものを書き換えたりすることができます。 Linux では netfilter
フレームワークが提供されていて、これによって様々なネットワークを個別に扱う効率的なファイアウオールを構築することができます。この netfilter
フレームワークのフロントエンドが iptables で、ルールセットを定義するための汎用的なテーブル構造を作成することができます。これにより、ネットワークインターフェイスからの通過を許可するパケットを、正確に制御することができます。また、 firewalld
やそのグラフィカルインターフェイスである firewall-config
を利用することでも、パケットフィルタを構築することができます。
openSUSE Leap 15.0 では新しいソフトウエアファイアウオールとして firewalld
が提供されています。これは SuSEfirewall2 を置き換えるべく提供されているものです。本章では firewalld
の設定方法のほか、古いバージョンの openSUSE Leap リリースからアップグレードしたユーザ向けに、 SuSEfirewall2 から firewalld
への移行方法をも説明しています。
本章では、パケットフィルタリングに関してパケット寄りの詳細を説明しています。 netfilter
と iptables
のコンポーネントは、ネットワークパケットのフィルタリングや内容の変更、そしてネットワークアドレス変換 (NAT) に関する制御を行う仕組みです。フィルタリングの判断条件とそれに付属する制御内容はチェインという形で保持され、パケットが届くごとにそれぞれ 1 つずつ判断を行います。 iptables
コマンドでは、これらのテーブルやルールの制御を行うことができます。
Linux カーネルでは 3 種類のテーブルを管理しています。これらはそれぞれ別々のフィルタ機能に対応しています:
このテーブルは、狭い意味での パケットフィルタリング を行うために提供されているテーブルで、様々なフィルタリングルールを設定して使用します。このテーブルでは、パケットの通過を許可する ( ACCEPT
) か拒否する ( DROP
) かを指定するなどして、ルールを構成します。
このテーブルは、パケットの発信元と送信先のアドレスをそれぞれ変更するために使用するテーブルです。これらの機能を利用することで、プライベートネットワークをインターネットに接続する際に使用する、 マスカレード と呼ばれる処理を実現することができます。
このテーブルは、 IP ヘッダなどに含まれている様々な値 (Type Of Service など) を制御するために使用するテーブルです。
これらのテーブルに対して、それぞれ下記に示すチェインが用意されています:
このチェインは、届いた全てのパケットを処理するためのチェインです。
このチェインは、このシステムが送信先となっている全てのパケットを処理するためのチェインです。
このチェインは、このシステムを通過していく全てのパケットを処理するためのチェインです。
このチェインは、このシステムから発信される全てのパケットを処理するためのチェインです。
このチェインは、発信される全てのパケットを処理するためのチェインです。
図23.1「iptables: パケットの流通経路」 の図には、 Linux システム内におけるパケットの流通経路を示しています。単純化する目的でチェインの中にテーブルを記述していますが、実際にはこれらのチェインはテーブル内に含まれる形になっています。
最もわかりやすい例として、 eth0
のインターフェイスに対して、このシステム宛のパケットが届いた場合を考えてみます。パケットは最初、 mangle
テーブル内の PREROUTING
チェインで処理され、その後 nat
テーブル内の PREROUTING
チェインで処理が行われます。その後、パケットの経路 (ルーティング) を判断する処理を行い、パケットの送信先が自分自身であるかどうかを判断します。今回は自分自身が宛先なので、 mangle
および filter
の INPUT
チェインで処理されたあと、 filter
テーブル内で許可される設定になっていれば、対応するプログラムに渡されることになります。
マスカレードとは Linux 固有の NAT (Network Address Translation; ネットワークアドレス変換) の一形態で、小規模な LAN をインターネットに接続する際に使用するものです。 LAN 内のホストにはプライベート IP アドレスの範囲 (詳しくは 13.1.2項 「ネットマスクとルーティング」 をお読みください) 内にあるアドレスを割り当ててあり、インターネット側にはプロバイダなどから割り当てられたアドレスを使用している場合、インターネットに接続するには、 LAN 側の IP アドレスをインターネット側のアドレスに変換する作業が必要となります。通常、この処理は LAN とインターネットを結ぶルータが行うべき作業です。一般的な構成は非常にシンプルで、ルータには複数のネットワークインターフェイス (通常はネットワークカード) があり、それとは別にインターネットに接続しているインターフェイスが用意されています。 LAN 内のコンピュータは、このルータをデフォルトゲートウエイとして設定することで、外部 (つまりインターネット) の世界に出て行くことができるようになっています。
ネットワークを設定する際、ブロードキャストアドレスとネットマスクは、 LAN 内の全てのコンピュータで同じ値を設定する必要があります。設定の異なるコンピュータが存在すると、正しい経路を見つけられなくなってしまうことがあります。
上述のとおり、 LAN 内のコンピュータがインターネットアドレス宛にパケットを送信する場合、デフォルトゲートウエイとして設定したルータに対して通信が行われます。ただし、ルータとして動作するにはあらかじめパケットを転送できるように設定しなければなりません。セキュリティ上の理由から、既定のインストールでは転送機能は有効化されません。有効化を行うには、 /etc/sysctl.conf
ファイル内に net.ipv4.ip_forward = 1
という行を追加してください。 YaST から設定を行いたい場合は、 yast routing ip-forwarding on
と入力して実行してください。
接続先の (インターネット側の) ホストからは、ルータまでは到達可能であるものの、本来のパケット送信元である内部ネットワーク内のコンピュータまでは到達できないようにしています。このような仕組みをマスカレード (仮装や変装などの意味) と言います。アドレス変換の仕組みにより、ルータは応答パケットに対する第一の送信先となります。ルータ側ではこのパケットがどれに紐付くものであるのかを探して、本来の (LAN 側の) 送信元に配送します。
内部側のネットワークパケットの配送はマスカレード処理用のテーブルに従って行われるため、外側 (インターネット側) から内側 (LAN 側) に接続を開くことはできなくなっています。これは、外部から内部に接続しようとしても、テーブル内に対応する項目が存在しないためです。これに加えて、既に確立されている接続に対しては、テーブル内でその状態を管理するようにもなっています。これにより、他の接続で使用されてしまうようなことがないようになっています。
このような構造になっていることから、 ICQ, cucme, IRC (DCC, CTCP), FTP (PORT モード) などのプロトコルを使用した場合、接続がうまくいかない場合があります。 Web ブラウザや標準的な FTP プログラムなど、多数のプログラムは PASV モードを使用しますので、フィルタリングやマスカレードという観点では問題が発生しにくくなっています。
ファイアウオール とはおそらく、ネットワーク間を流れるデータを制御する仕組みとして最もよく使われている用語でしょう。厳密に言うと、本章で説明している内容は パケットフィルタ と呼ばれる仕組みです。パケットフィルタはプロトコルやポート、 IP アドレスなどの条件を元に、データの流れを管理するための仕組みです。この仕組みによって、ネットワークに対して届いて欲しくないパケットを防ぐことができます。たとえば Web サーバなど、一般的に広くアクセスを許すサービスを提供するような場合、明示的に対応するポートを開くように設定する必要があります。しかしながら、一般にパケットフィルタではパケットの内容までは判断できませんので、アドレス情報などが間違っていない限り、 Web サーバとの通信はできてしまいます。つまり、 Web サーバ内で動作する CGI プログラムを不正に操作するようなパケットが届いたとしても、パケットフィルタではそれを防ぐことができず、通過させてしまうことになります。
より効率的で複雑な構成を取るとすれば、アプリケーションゲートウエイやプロキシなどとパケットフィルタを組み合わせて、多階層の防御を行う方法があります。この場合、パケットフィルタは許可していないポート宛の通信を拒否し、それを通過したパケットのみがアプリケーションゲートウエイやプロキシに渡されます。このゲートウエイやプロキシは、サーバとクライアントとの間の仲介役として動作し、アプリケーションが使用するプロトコルを直接解釈してやり取りを行います。このようなアプリケーションゲートウエイやプロキシとして代表的なものが Squid です。こちらは HTTP/FTP のプロキシサーバとして動作するもので、 HTTP ページや FTP ファイルへのアクセスは、プロキシキャッシュ内に記憶していればその内容をそのまま提供し、キャッシュ内に存在していなければ直接アクセスしてページを提供することができます。
下記の章では、 openSUSE Leap に付属しているパケットフィルタ機能について説明しています。パケットフィルタやファイアウオールに関する詳細は、 Firewall HOWTO (英語) でも提供されています。
firewalld
#Edit sourcefirewalld
による SuSEfirewall2 の置き換えについてopenSUSE Leap 15.0 15 では SuSEfirewall2 の置き換えとして firewalld
が新しい既定のファイアウオールになっています。 openSUSE Leap 15.0 以前のバージョンからアップグレードしている場合は、 SuSEfirewall2 が従来どおりインストールされたままの状態になりますので、手作業で firewalld
に移行を行ってください (詳しくは 23.5項 「SuSEfirewall2 からの移行」 をお読みください) 。
firewalld
はシステム内にある iptables
のルールを管理し、 D-Bus インターフェイス経由で操作することのできるデーモンです。対応するコマンドラインユーティリティ firewall-cmd
と、グラフィカルユーザインターフェイス firewall-config
がそれぞれ用意されています。 firewalld
は裏で動作する仕組みであることから、たとえば仮想マシンのネットワーク設定を行うなど、 iptables のルールに対してアプリケーション側から変更要求を送信することができるようになっています。
firewalld
ではセキュリティゾーンと呼ばれる仕組みを提供しています。既定の設定では、 internal
(内部) や public
(公共) などのゾーンが用意されています。それ以外のゾーンが必要な場合でも、管理者側で自由に設定することができます。各ゾーンにはそれぞれ対応する iptables のルールを設定することができます。また、ネットワークインターフェイスはいずれか 1 つのゾーンに属するように設定するほか、発信元のアドレスをベースにして接続ごとにゾーンを割り当てることもできます。
それぞれのゾーンは信頼レベルを表していて、たとえば public
はインターネットや無線ホットスポットに対して設定すべきゾーンで、最も信頼レベルの低いネットワークを表しています。逆に internal
は、家庭内のネットワークや企業内のネットワークなど、最も信頼できるネットワークを表しています。このように信頼レベルを分けることで、接続されるネットワークごとに異なるルールを適用できるようにしています。
firewalld
の既定で設定されているゾーンとその意味について、詳しくは https://www.firewalld.org/documentation/zone/predefined-zones.html (英語) にあるマニュアルをお読みください。
ネットワークインターフェイスに対する設定を行っていない場合、そのインターフェイスには何もゾーンが割り当てられません。この場合、 firewall-cmd --get-default-zone
で表示される既定のゾーンが割り当てられます。既定のゾーンを何も設定していない場合、既定値は public
(公共) になっています。
firewalld
のパケットフィルタリングでは、接続の開始側については基本的に許可される設定になっています。接続の開始側とは、手元のコンピュータから相手のコンピュータに対して、接続を始める種類の接続を意味しています。逆に、接続を受け入れる側の場合は、ゾーンの設定で明示的に許可を指定しない限り、アクセスが拒否されるようになっています。そのため、何らかのサービスの接続を受け入れるインターフェイスに対しては、適切なゾーンを指定しておいて、ゾーン内で必要なサービスの許可を設定してください。
firewalld
では、もう 1 つ重要な考え方があります。それは 一時的な 設定と 恒久的な 設定です。一時的な設定とは現在動作中のルールそのものを表していて、恒久的な設定とは次回の firewalld
の再起動で適用される、保存済みのルールを表しています。これにより、次に firewalld
を再起動するまでの間、一時的に適用するルールを設定することができますので、実験的にルールを追加してみて、うまくいかなければ元に戻すと言ったことが容易に実現できるようになっています。なお、設定を変更する際には、どちらの設定を編集しているのかをよくお確かめください。こちらについての詳細は、 23.4.1.2項 「一時的な設定と恒久的な設定の違い」 で説明しています。
firewalld
をグラフィカルユーザインターフェイス firewall-config
で操作したい場合は、 ドキュメンテーション (英語) をお読みになることをお勧めします。以下の章では、コマンドライン経由で利用する firewall-cmd
で firewalld
の制御を行っています。
firewalld
は既定でインストールされ、有効化されます。 firewalld
は通常の systemd
サービスとして設定されていますので、 systemctl
や サービスマネージャ で設定することができます。
インストールを行うと、 YaST は firewalld
を自動的に起動して、全てのインターフェイスを既定値の public
ゾーンに割り当てます。何らかのサーバアプリケーションをインストールしていて、システム内で有効化している場合は、 YaST 側で でインターフェイスを選択するか、もしくは を選択することで、自動的にファイアウオールの設定を行うことができます。また、サーバモジュールによっては、 ボタンを押すことで、追加のサービスやポートを開くように設定することもできます。
既定では、 firewall-cmd
は一時的な設定に対して作用し、恒久的な設定は変更しません。恒久的に設定を変更したい場合は、 --permanent
オプションを追加してください。なお、 --permanent
オプションを指定した場合、一時的な設定には反映されず、即時に反映されることもありません。現時点では両方に対して一回で設定する機能は用意されていませんが、一時的な設定を恒久的な設定にコピーすることは可能です。コピーを行うには、下記のように実行します:
#
firewall-cmd --runtime-to-permanent
上記を実行することで、現時点での一時的な設定を恒久的な設定として書き込むことができます。これにより、コマンドラインやその他のプログラムなどで一時的な設定に書き込んだ場合でも、それを恒久的に保存することができるようになります。ただし、より安全に作業を行いたい場合は、恒久的な設定に新しいルールを追加して、 firewalld
を再起動することで有効化することもできます。
なお、既定のゾーンなど一部の設定は、一時的な設定と恒久的な設定で異なる管理を行っていません。これらの設定を変更した場合は、両方の設定に対して反映されます。
逆に、一時的に設定を変更していて、その変更を取り消したい場合は、下記のいずれかを実行してください。前者は firewalld
のコマンドラインインターフェイスを介して、後者は systemd
を介して実施しています:
#
firewall-cmd --reload
#
systemctl reload firewalld
以下の章では、記述を簡略化する目的で、常に一時的な設定に対して作業を行っています。恒久的な設定に書き込みたい場合は、対応するオプションを付与して実行してください。
ゾーンが割り当てられている全てのネットワークインターフェイスを表示したい場合は、下記のように実行します:
#
firewall-cmd --zone=public --list-interfaces
eth0
同様に、インターフェイス名を指定してゾーンを問い合わせることもできます:
#
firewall-cmd --get-zone-of-interface=eth0
public
下記のコマンドラインは、インターフェイスをゾーンに割り当てるコマンドラインです。なお、 --add-interface
は eth0
がどのゾーンにも割り当てられていない場合にのみ動作します。 --change-interface
は、どちらの場合でも動作します。この場合、既にゾーンへの割り当てが存在していると、そのゾーンに対する割り当てを外す動作になります:
#
firewall-cmd --zone=internal --add-interface=eth0
#
firewall-cmd --zone=internal --change-interface=eth0
なお、明示的に --zone
オプションでゾーンを指定しない場合は、既定のゾーンが指定されたものとして扱われます。下記のコマンドは、それぞれ既定のゾーンが何であるのかを問い合わせ、既定のゾーンを特定のゾーンに設定するコマンドです:
#
firewall-cmd --get-default-zone
dmz#
firewall-cmd --set-default-zone=public
特定のゾーンに割り当てられていないネットワークインターフェイスは、自動的に既定のゾーンに割り当てられているものとして扱われます。また、既定のゾーンの変更は即時に反映され、かつ恒久的にも保存されます。そのため、 internal
などのセキュリティの低いゾーンを既定のゾーンに設定したりしてはなりません。これにより、お使いのコンピュータを不用意に危険にさらすことになってしまいます。たとえば USB イーサネットなどのホットプラグ型インターフェイスを接続した場合、既定のゾーンが internal
ゾーンであるとすると、接続を開始した直後からネットワークの接続を信頼してしまうことになります。
また、ゾーンのインターフェイス一覧には、明示的にゾーンが指定されているもの以外は表示されないことにも注意してください。現時点では、ゾーンの割り当てのないインターフェイスを表示するコマンドはありません。このような理由から、通常使用するネットワークインターフェイスについては、必ずゾーンを割り当てるようにしておいてください。
firewalld
には サービス という考え方があります。サービスは 1 つ以上のポートやプロトコルの定義から構成されるもので、 Web やメールサーバのプロトコルなどのように、まとめて使用することになるポートやプロトコルを一括で指定できるように構成しているものです。下記のコマンドでは、サービス名を指定してその詳細情報を取得しています:
#
firewall-cmd --get-services
[...] dhcp dhcpv6 dhcpv6-client dns docker-registry [...]#
firewall-cmd --info-service dhcp
dhcp ports: 67/udp protocols: source-ports: modules: destination:
これらのサービス定義は、ゾーン内で特定の機能をまとめて有効化したい場合に使用します。たとえば下記のようにコマンドを入力して実行すると、 internal
ゾーンに対して HTTP (Web サーバ) のポートを開くことができます:
#
firewall-cmd --add-service=http --zone=internal
特定のゾーンに対してサービスの許可を取り消したい場合は、逆のサブコマンドである --remove-service
を使用します。新しくサービスを定義したい場合は、 --new-service
サブコマンドを使用します。詳しくは https://www.firewalld.org/documentation/howto/add-a-service.html (英語) をお読みください。
ポート番号を直接指定してポートを開きたい場合は、下記のように入力して実行します。下記の例では、 internal
ゾーンに対して TCP ポート 8000 を開きます:
#
firewall-cmd --add-port=8000/tcp --zone=internal
ポートを閉じたい場合は、逆のサブコマンドである --remove-port
をお使いください。
firewalld
には特定のサービスやポートを指定した時間内のみ開くことのできる、 --timeout
というパラメータが用意されています。これは簡易的なテストに有用な仕組みで、サービスやポートを閉じ忘れることを防止することができます。たとえば internal
ゾーンに対して 5 分間だけ imap
サービスを許可したい場合は、下記のように実行します:
#
firewall-cmd --add-service=imap --zone=internal --timeout=5m
firewalld
には、そのファイアウオールのルールが有効な間は変更を禁止することのできる、 ロックダウンモード が用意されています。アプリケーション側からは D-Bus インターフェイスを介して自動的にファイアウオールのルールを変更することができてしまうほか、 PolicyKit のルールに従って一般ユーザからも同じことを実施できてしまいますので、状況によっては変更の防止が有用となることがあります。詳しくは https://fedoraproject.org/wiki/Features/FirewalldLockdown をお読みください。
なお、ロックダウンモードは実際のセキュリティを提供するものではなく、不用意に設定を変更してしまったりする行為を防止するための仕組みです。 firewalld
でのロックダウンモードは、不正アクセスからの防御にはなっていないことに注意してください。詳しくは https://seclists.org/oss-sec/2017/q3/139 (英語) をお読みください。
iptables
ルールの追加 #Edit sourcefirewalld
はコンピュータ内の netfilter
ルールに対して、排他的にアクセスすることによって成り立っています。そのため、 iptables
のようなコマンドで、ファイアウオールのルールを直接書き換えたりすべきではありません。これにより、 firewalld
の動作が不安定になってしまったり、セキュリティや機能性が損なわれてしまったりする危険性があります。
firewalld
ではカバーしていない独自のファイアウオールルールを追加する必要がある場合は、 2 種類ある方法のうちのいずれかを実施してください。 1 つは iptables
で設定する内容をそのまま firewalld
に投げる方法で、この場合は --direct
オプションを指定します。このとき、 iptables
を実行する際のテーブルやチェイン、優先度に関する指定を行う必要があります。下記の例では、 FORWARD チェインに対して独自の追跡 (tracking) ルールを追加しています:
#
firewall-cmd --direct --add-rule ipv4 filter FORWARD 0 -i eth0 -o eth1 \ -p tcp --dport 80 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
それ以外にも、 firewalld
では リッチルール と呼ばれる仕組みにも対応しています。この方法のほうが iptables
のルールを簡単に指定することができます。詳しくは https://www.firewalld.org/documentation/man-pages/firewalld.richlanguage.html (英語) をお読みください。下記の例では、特定の発信元アドレスからの IPv4 パケットを drop (処理せず落とす) する設定を行っています:
#
firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" \ source address="192.168.2.4" drop'
firewalld
は完全機能のルータとして動作するようには設計されていません。ですが、一般的な家庭用ルータ程度の設定であれば可能です。企業内の本番環境で使用されるようなルータの場合は、 firewalld
を使用すべきではありません。ルータやファイアウオールとして専用に設計された機器をお使いください。下記の章では、 firewalld
内でルーティングを扱うにあたっての、いくつかの情報源を示しています:
IP プロトコルの経路制御を有効化するのに必要な情報は、 23.2項 「基本的なマスカレード処理」 に概要があります。
internal
ゾーンに対して IPv4 マスカレードを有効化するには、下記のコマンドを実行します。
#
firewall-cmd --zone=internal --add-masquerade
firewalld
ではポート転送の設定も行うことができます。たとえば下記のコマンドを実行すると、ポート 80 宛に届いた通信を他のホストに転送することができます:
#
firewall-cmd --zone=public \ --add-forward-port=port=80:proto=tcp:toport=80:toaddr=192.168.1.10
ネットワークサービスによっては、特定のポート番号で待ち受けていないものがあります。この場合、 portmapper
や rpcbind
のプロトコルをベースにして動作しています (以降は rpcbind
と表現します) 。これらのサービスが開始されると、ローカル側のポートをランダムに選択したあと、 rpcbind
と通信を行って、このポートを既知のものとして使用するようにします。 rpcbind
それ自身は特定の (既知の) ポート上で動作します。ネットワーク上離れたシステムからは、 rpcbind
に対して問い合わせを行い、どのポートで動作しているのかを確認します。現在、この仕組みはそれほど多くのプログラムで使用していないものですが、 Network Information Services (NIS; ypserv
および ypbind
) と Network File System (NFS) バージョン 3 で使用されています。
新しい NFSv4 では、 TCP ポート 2049 という既知のポート単独で動作するようになっています。プロトコルバージョン 4.0 では、カーネルのパラメータ fs.nfs.nfs_callback_tcpport
で固定のポートを指定する必要があります (詳しくは 例23.1「/etc/modprobe.d/60-nfs.conf
内での nfs
カーネルモジュールに対するコールバックポートの設定」 をお読みください) 。プロトコルバージョン 4.1 以降であれば、この設定も不要となっています。
rpcbind
プロトコルを使用する仕組みでは、動的にポートが設定されるため、ファイアウオール経由でサービスにアクセスできるようにすることが難しくなっています。 firewalld
では、それ単体でこれらのサービスに対応することができません。手作業で作業を行う場合は、 23.4.2.1項 「ポートを固定するための設定」 をお読みください。それ以外にも、 openSUSE Leap にはヘルパースクリプトが用意されています。詳しくは 23.4.2.2項 「固定のポートを設定するための firewall-rpcbind-helper の使用」 をお読みください。
問題を解決するための方法のうちの 1 つとして、各ネットワークサービスの使用するポートを固定する方法があります。これを設定することで、 firewalld
でポートを開くように設定することができるようになり、全てが問題なく動作するようになります。ポート番号の指定は自由に決めることができますが、他のサービスで使用されてしまうことを防ぐため、既知の (いわゆる well-known な) ポート範囲以外から設定しておくことをお勧めします。 NIS や NFSv3 のサービスに対する設定項目の一覧については、 表23.1「ポートを固定させるための主な sysconfig 変数」 をお読みください。ただし、 NIS や NFS の設定によっては、これら全てのポートを設定する必要がない場合もあります。
ファイルパス |
変数名 |
値の例 |
---|---|---|
/etc/sysconfig/nfs | MOUNTD_PORT | 21001 |
STATD_PORT | 21002 | |
LOCKD_TCPPORT | 21003 | |
LOCKD_UDPPORT | 21003 | |
RQUOTAD_PORT | 21004 | |
/etc/sysconfig/ypbind | YPBIND_OPTIONS | -p 24500 |
/etc/sysconfig/ypserv | YPXFRD_ARGS | -p 24501 |
YPSERV_ARGS | -p 24502 | |
YPPASSWDD_ARGS | --port 24503 |
設定を反映させるには、対応するサービスをそれぞれ再起動する必要があります。なお、 rpcinfo -p
と入力して実行することで、割り当てられた rpcbind のポートを表示することもできます。正しく設定がされていれば、ここに固定のポートが表示されるはずです。
ユーザスペース内で動作しているネットワーク向けのポート設定とは別に、 Linux カーネルが NFS に対して直接使用するポートも存在しています。これらのポートのうちの 1 つは nfs_callback_tcpport
と呼ばれます。このポートは、バージョン 4.1 以前の NFS プロトコルでのみ必要となります。ここで使用するポートは、 sysctl の fs.nfs.nfs_callback_tcpport
で設定することができます。この sysctl ノードは、 NFS マウントが有効な場合にのみ動的に現れます。そのため、この設定はカーネルモジュールのパラメータとして設定しておくことが最適です。これは 例23.1「/etc/modprobe.d/60-nfs.conf
内での nfs
カーネルモジュールに対するコールバックポートの設定」 で示している設定で実現することができます。
/etc/modprobe.d/60-nfs.conf
内での nfs
カーネルモジュールに対するコールバックポートの設定 #options nfs callback_tcpport=21005
この設定を反映させるのに最も簡単な方法は、マシンの再起動です。マシンを再起動しないで適用するには、 NFS 関連のサービスを全て停止させて nfs
カーネルモジュールを読み込みなおす必要があります。なお、現時点での NFS コールバックポートを確認したい場合は、 cat /sys/module/nfs/parameters/callback_tcpport
と入力して実行してください。
このようにして RPC 関連のポートを固定化したら、あとは新しい firewalld
サービス定義を作成して、使用するようにすると便利です。このサービス定義は関連する全てのポートを含むもので、これによって一括でポートを許可するように設定することができます。 例23.2「NFS 向けの新しい firewalld
RPC サービスの設定コマンド」 には、新しくサービスを定義して、それらの固定ポートをサービス内に設定し、使用するまでの手順を示しています。
firewalld
RPC サービスの設定コマンド ##
firewall-cmd --permanent --new-service=nfs-rpc
#
firewall-cmd --permanent --service=nfs-rpc --set-description="NFS related, statically configured RPC ports"
# TCP/UDP ポートを順序通りにサービスに追加する#
for port in 21001 21002 21003 21004; do firewall-cmd --permanent --service=nfs-rpc --add-port ${port}/udp --add-port ${port}/tcp done
# コールバックポートは TCP のみ#
firewall-cmd --permanent --service=nfs-rpc --add-port 21005/tcp
# 新しく定義したサービスの詳細表示#
firewall-cmd --info-service=nfs-rpc --permanent -v
nfs-rpc summary: description: NFS and related, statically configured RPC ports ports: 4711/tcp 21001/udp 21001/tcp 21002/udp 21002/tcp 21003/udp 21003/tcp 21004/udp 21004/tcp protocols: source-ports: modules: destination: # firewalld を再読み込みさせて、新しいサービス定義を利用できるようにする#
firewall-cmd --reload
# 新しいサービス定義を internal ゾーンに追加する#
firewall-cmd --add-service=nfs-rpc --zone=internal
上記の章で示した固定のポートを設定するための手順は、 SUSE が提供する firewall-rpc-helper.py
というツールを使用することで、より簡単に行うことができます。このツールは、 zypper in firewalld-rpcbind-helper
でインストールすることができます。
このツールは、上記の章で実施したサービス設定を対話に設定するツールです。このほか、現時点でのポートの割り当てを表示することができるほか、スクリプト内で使用することもできるようになっています。詳しくは firewall-rpc-helper.py --help
を実行して出力された内容をお読みください。
firewalld
では、既定のバックエンドとして nftables を使用します。 nftables は Linux netfilter
プロジェクトが提供するフレームワークで、パケットフィルタリングのほか、ネットワークアドレス変換 (NAT) 等の機能を提供します。また、 nftables はコネクショントラッキングやユーザスペースキューイング、ロギングやフック機能などの既存の netfilter サブシステムを流用した仕組みで、 iptables, ip6tables, arptables, ebtables, ipset 等の代替として機能するものとなっています。
nftables を使用することの利点としては、下記のようなものがあります:
IPv4, IPv6 の両プロトコルに対して 1 つのフレームワークで対応できます。
ルールはルールセット全体の再読み込みや更新、保存などを行うことなく適用することができます。
イベントの追跡は nft ツールで、ルールセットのデバッグやトレースは nftrace でそれぞれ行うことができます。
nft
コマンドラインツールは、ルールを netlink 形式の VM バイトコードにコンパイルします。逆にルールセットを取り出す際は、 VM バイトコードを元のルールセット表記に翻訳して出力します。
基本的な nftables の設定ファイル:
>
cat /etc/nftables.conf
#!/usr/sbin/nft -f
flush ruleset
# IPv4 と IPv6 の両方にマッチします
table inet filter {
# チェイン名は任意に設定できます。
# どのトラフィックを処理するのかについては、
# type 以下で指定します。
chain input {
type filter hook input priority 0; policy accept;
}
chain forward {
type filter hook forward priority 0; policy accept;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
上記の例では、全てのチェインで accept ポリシーを設定していることから、全てのトラフィックを許可することになります。もちろん実際には全てのトラフィックが既定で拒否されますので、必要なトラフィックのみを許可するように設定するのが適切です。
マスカレードを使用する nftables の設定:
>
cat /etc/nftables.conf
#!/sbin/nft -f
flush ruleset
table ip nat {
chain prerouting {
type nat hook prerouting priority 0; policy accept;
}
# WAN 宛に送信される全てのトラフィックに対して、経路の判断後に
# 発信元アドレスを WAN インターフェイスのプライマリ IP アドレスに置き換えます。
chain postrouting {
type nat hook postrouting priority 100; policy accept;
oifname "wan0" masquerade
}
}
固定 IP の環境であれば、マスカレードではなくソース NAT (SNAT) を使用したほうが少しだけ高速になります。これは、それぞれの発信パケットの置き換え時にあらかじめ IP アドレスが分かっていたほうが、手っ取り早く処理できるためです。
いくつかのルールを適用した nftables の設定ファイル:
>
cat /etc/nftables.conf
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain base_checks {
## 接続状態の確認を行う追加のルールセットです。
# 確立済みの接続や関連する接続は自動的に許可します
ct state {established, related} accept;
# 不正な接続に対しては早めに廃棄します
ct state invalid drop;
}
chain input {
type filter hook input priority 0; policy drop;
# ループバック接続を許可します
iif "lo" accept;
jump base_checks;
# ICMP, IGMP を許可します
ip6 nexthdr icmpv6 icmpv6 type { echo-request, echo-reply, packet-too-big, time-exceeded, parameter-problem, destination-unreachable, packet-too-big, mld-listener-query, mld-listener-report, mld-listener-reduction, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, ind-neighbor-solicit, ind-neighbor-advert, mld2-listener-report } accept;
ip protocol icmp icmp type { echo-request, echo-reply, destination-unreachable, router-solicitation, router-advertisement, time-exceeded, parameter-problem } accept;
ip protocol igmp accept;
# ログを記録して拒否するテストです
counter log prefix "[nftables] input reject " reject;
}
chain forward {
type filter hook forward priority 0; policy accept;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
上記の例は、下記のようになっています:
input チェインの既定値は drop (廃棄) で、末尾に reject (拒否) ルールが設定されているため、全ての到着トラフィックをブロックする設定になっています。
localhost
インターフェイスの全てのトラフィックを許可しています。
base_checks
チェインでは、全てのパケットに対して既存の接続に関係したものであるかどうかを確認しています。これにより、こちらからの接続に対する応答はブロックされないようになります。
ICMP, IGMP の各パケットは、タイプ名を指定したセットを使用することでそれぞれ許可しています。
カウンタは、直近にリセットされた時点からの合計パケット数や合計バイト数を保持する仕組みです。 nftables の場合、カウンタを実装したいルールでそれぞれ指定しなければなりません。
firewalld
設定の作成についてAutoYaST で firewalld
の設定を作成する方法について、詳しくは AutoYaST ガイド 内の ファイアウオール設定 の章をお読みください。
openSUSE Leap 15.0 以前の任意のバージョン からopenSUSE Leap 15.7 にアップグレードした場合は、 SuSEfirewall2 はそのまま保持され、動作し続けるようになっています。 SuSEfirewall2 から firewalld
への自動的な移行の仕組みは提供されていないことから、移行作業は手作業で実施する必要があります。ただし、 firewalld
には susefirewall2-to-firewalld
と呼ばれる移行支援ツールが用意されていますので、こちらをお使いいただくことができます。ですが、このツールはご利用いただいている SuSEfirewall2 の設定の複雑さによって、全く問題なく移行できる場合から、全く支援にならない場合までさまざまな結果になります。通常は部分的に移行が行われ、残りは手作業で firewalld
の設定を調整して対応する必要が発生します。
このツールが生成した設定は、 SuSEfirewall2 と同じような動作になるようになります。そのような背景から、 firewalld
の機能を完全に発揮するには、既存の設定の移行ではなく全く新しく設定を作成し直すことをお考えください。また、 susefirewall2-to-firewalld
に何もオプションを付けずに実行した場合は、恒久的な変更は行われなくなっていますが、ネットワーク上離れた場所から管理を行っているような場合は、移行によって締め出されてしまうこともあります。
susefirewall2-to-firewalld
をインストールして実行するには、下記の手順を実施します:
#
zypper in susefirewall2-to-firewalld#
susefirewall2-to-firewalld INFO: Reading the /etc/sysconfig/SuSEfirewall2 file INFO: Ensuring all firewall services are in a well-known state. INFO: This will start/stop/restart firewall services and it's likely INFO: to cause network disruption. INFO: If you do not wish for this to happen, please stop the script now! 5...4...3...2...1...Lets do it! INFO: Stopping firewalld INFO: Restarting SuSEfirewall2_init INFO: Restarting SuSEfirewall2 INFO: DIRECT: Adding direct rule="ipv4 -t filter -A INPUT -p udp -m udp --dport 5353 -m pkttype --pkt-type multicast -j ACCEPT" [...] INFO: Enabling direct rule=ipv6 -t filter -A INPUT -p udp -m udp --dport 546 -j ACCEPT INFO: Enabling direct rule=ipv6 -t filter -A INPUT -p udp -m udp --dport 5353 -m pkttype --pkt-type multicast -j ACCEPT INFO: Enable logging for denied packets INFO: ########################################################## INFO: INFO: The dry-run has been completed. Please check the above output to ensure INFO: that everything looks good. INFO: INFO: ########################################################### INFO: Stopping firewalld INFO: Restarting SuSEfirewall2_init INFO: Restarting SuSEfirewall2
このスクリプトを実行するとさまざまな出力が生成されますが、これをファイルに保存しておくことで、後からゆっくり読むことができるようになります:
#
susefirewall2-to-firewalld | tee newfirewallrules.txt
このスクリプトには、下記のオプションが用意されています:
-c
変更点を恒久的に保存します。提示された設定で問題が無い場合にのみ、このオプションを指定してください。また、既存の firewalld
の設定は リセットされます ので、必ずバックアップを採取しておいてください!
-d
動作に関する詳細な情報を出力します。このスクリプトのバグを報告したい場合などに有用ですが、機密情報が含まれることもあります。
-h
このメッセージを表示します。
-q
出力を抑制します。エラーメッセージも表示されなくなります!
-v
冗長モードを指定します。警告メッセージやその他の情報に関するメッセージが出力されるようになります。
firewalld
パッケージに対する最新の情報と、その他のドキュメンテーションについては、 /usr/share/doc/packages/firewalld
内で提供されています。 netfilter および iptables プロジェクトの Web ページは https://www.netfilter.org にあります。こちらには、多数の言語に対応した iptables 関連の文書が多数用意されています。