犬でも分かるLinuxネットワーク設定(6):ルーティングとNAT

ネットワークで接続された機器は、基本的には同一セグメントのネットワーク内でしか通信ができません。でも、家の中からインターネットのサービスにも接続できていますよね。それは、ルーターが異なるセグメント間にまたがって通信を転送(ルーティング)してくれているからです。今回は、Linuxサーバ上でfirewalldを稼働させて、サーバをルーターとして機能させるための設定方法を解説します。

ウチのネットワーク構成

ウチのネットワーク環境は以下の図の通りになっています。契約しているプロバイダから提供されたホームルーターのLAN側(以下「ホームネットワーク」と呼びます)にPC等を接続しています。ホームルーターは文字通りルータの機能を提供しているので、ホームネットワークに接続された機器は、ホームルーターを仲介してインターネットへのアクセスが可能です(図中の水色の点線)。

ウチにはホームネットワークの他に、サーバやネットワークのテストのために、別のネットワーク(以下「管理ネットワーク」と呼びます)を構築していて、base1というミニPCは管理ネットワークだけに接続されています。

ルーターとデフォルトゲートウェイについて

同じセグメント内の機器同士は、直接ネットワーク通信が可能です。でも、異なるセグメントのIPアドレスに対しては直接通信ができません。異なるセグメントのIPアドレスに対して通信をしたいのであれば、セグメント間にまたがって通信を転送してくれる「ルーター」が必要です。そして、自分が接続しているセグメントとは異なる宛て先と通信したいとき、通信をどのルーターに転送するのかを指定する必要がありますが、デフォルトの転送先となるのが「デフォルトゲートウェイ」です。
尚、各機器において指定できるデフォルトゲートウェイは1つです。

デフォルトゲートウェイの指定だけではルーティングしてくれない

前述のネットワーク構成において、ホームネットワークに接続しているホストbase0は、デフォルトゲートウェイにホームルーターのIPアドレス「192.168.1.1」を指定していおり、ホームルータを仲介してインターネットにアクセスができます。以下はネットワーク接続形態を簡素化した図です。

ホームルーターがこの通信(パケット)をインターネットに転送するときには、アクセス元のIPアドレスを、ホームルーターが持っているインターネット上のグローバルのIPアドレスに変換して転送します。この変換処理のことを「NAT(Network Address Translation)」と呼びます。インターネット上のIPアドレスに変換する理由は、通信相手がパケットを返すときに、インターネット上のIPアドレスにしておかないと返す宛て先が分からないからです。

上の図では、ホストbase0は192.168.2.0/24の管理ネットワークにも接続しています。管理ネットワークには ホストbase1が接続されていて、いろんなOSをインストールするテストに使っています。
さて、管理ネットワークだけに接続しているbase1は、インターネットに接続できるのでしょうか。base1ではデフォルトゲートウェイに、base0の管理ネットワークのIPアドレス「192.168.2.200」を指定していますので、管理ネットワーク以外を宛て先とする通信はbase0に転送します。しかし、base0はルーターの機能を持っていないので、base1から送られてきたパケットを次のデフォルトゲートウェイ(192.168.1.1)に転送してくれません。
すなわち、機器はデフォルトゲートウェイに指定されたIPアドレスにパケットを送信するのだけれど、送信した相手がルーターの機能を持っていなければ、次のデフォルトゲートウェイに転送なんてしてくれないのです。

firewalldでNATを使ってルーティングの機能を実現する

Rocky Linux9のサーバをルーターとして機能させるには、firewalldを使います。firewalldの名前から単なるファイヤーウォール(通信のフィルタリング)の機能を思い浮かべますが、ルーティングの機能を持っています。古いRHEL系OSでは iptablesがその機能を有していましたが、RHEL/CentOS7からfirewalldを使用するように変更されているとのことです。

以下の図は、ホストbase0でfirewalldのNATの機能を使ってルーティングを有効にした場合の通信イメージです。base1がインターネット上のIPアドレスを宛て先として通信するときには、
①パケットはまずbase1のデフォルトゲートウェイであるbase0(192.168.2.200)に転送される
②次に、base0のfirewalldでNATされて次のデフォルトゲートウェイであるホームルーター(192.168.1.1)に転送される
②最後に、ホームルーターでNATされてインターネットに出て行く
という通信となります。図中ではIPアドレスの変換が分かりやすいように、色を変えています。

firewalldにおけるNATの設定方法

まずはfirewalldの基本事項を…

firewalldはネットワークをゾーンで管理しています。ネットワークのインターフェース(あるいはコネクション)を作成すると、デフォルトで「public」という名前のゾーンに所属するようです。
firewalldが管理している全てのゾーンと、ゾーンに所属しているインターフェースを以下のコマンドで確認してみましょう。

# firewall-cmd --list-all-zones

インターフェースが所属しているゾーンは以下の通りでした(出力を抜粋)。

public (active)
target: default
icmp-block-inversion: no
interfaces: bond2 br1 br2 enp0s21f0u2c2 enp2s0 enp3s0
sources:
services: cockpit dhcpv6-client ssh
ports:
protocols:
forward: yes
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:

libvirt (active)
target: ACCEPT
icmp-block-inversion: no
interfaces: virbr0
sources:
services: dhcp dhcpv6 dns ssh tftp
ports:
protocols: icmp ipv6-icmp
forward: no
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
rule priority="32767" reject

virbr0はKVMが作成する仮想ブリッジですので、今回は無視します。
publicのほうに、bond2 br1 br2 enp0s21f0u2c2 enp2s0 enp3s0 のように多くのインターフェースが所属しているのは、ホストbase0では、ethernetデバイスだけでなく、bondingデバイス、仮想ブリッジを作成しているためです。インターフェースと接続しているネットワークの関係は以下の通りです。

・br1, enp0s21f0u2c2: ホームネットワークに接続(詳細はコチラをご覧ください)
・bond2 ,br2, enp2s0, enp3s0: 管理ネットワークに接続(詳細はコチラをご覧ください)

ウチの環境では、いろいろなテストをしている理由から、bondingやら仮想ブリッジやらを作っていますが、通常、ホストとネットワークは1つのネットワークインターフェースで接続されています。

管理ネットワークに接続するインターフェースのゾーンを別にする

最初に、管理ネットワークに接続するインターフェースとホームネットワークに接続するインターフェースを別々のゾーンに割り当てます。ホームネットワークに接続するインターフェースは「public」のままにしておいて、管理ネットワークに接続するインターフェースは「trusted」に移動させます。
ゾーン「trusted」は、targetがACCEPTに設定されており、アクセス制限がありません。

インターフェースbond2 ,br2, enp2s0, enp3s0のゾーンをtrustedに設定するには、nmcliコマンドを使って以下のように実行します(インターフェースに対する設定ではありますが、指定するのはコネクション名のほうなので、各インターフェースに対応するコネクション名を確認しておいてください。

# nmcli connection modify br2 connection.zone trusted
# nmcli connection modify br-slave-bond2 connection.zone trusted
# nmcli connection modify bond-slave-enp2s0 connection.zone trusted
# nmcli connection modify bond-slave-enp3s0 connection.zone trusted

実行した後、「firewall-cmd --list-all --zone=trusted」を実行して、ゾーンtrustedの情報を確認すると、以下の通りとなっています。

# firewall-cmd --list-all --zone=trusted
trusted (active)
target: ACCEPT
icmp-block-inversion: no
interfaces: bond2 br2 enp2s0 enp3s0
sources:
services:
ports:
protocols:
forward: yes
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:

publicのほうにIPマスカレードを設定する

管理ネットワークからbase0を経由してホームネットワークに出て行くパケットがNATされるように、ゾーン「public」のほうにIPマスカレードの設定を追加します。IPマスカレードはNATを実現する手段のひとつです。IPマスカレードではNATをするときに、送信元のIPアドレスはひとつのままで、送信元のport番号を変えて(動的に決定)通信を識別します。

ゾーン「public」にIPマスカレードを設定する方法は以下の通りです(successが表示されたら成功です)。尚、「firewall-cmd --runtime-to-permanent」を実行しないと、ランタイムには設定されるけれども設定が永続化されないので、実行して設定を保存しましょう。

# firewall-cmd --zone=public --add-masquerade
success
# firewall-cmd --runtime-to-permanent
success

IPマスカレードの設定状態は以下のコマンドで確認可能です。また「firewall-cmd –list-all-zones」でも確認することができます。

# firewall-cmd --zone=public --query-masquerade
yes

NATポリシーを作成する

ゾーン「trusted」を入力(ingress)、ゾーン「public」を出力(egress)としたNATポリシー(今回作成するポリシーの名前は「natPolicy」としています)を作成します。

# firewall-cmd --permanent --new-policy natPolicy
success
# firewall-cmd --permanent --policy natPolicy --set-target ACCEPT
success
# firewall-cmd --permanent --policy natPolicy --add-ingress-zone trusted
success
# firewall-cmd --reload
success

さっきとはちょっと違う方法を変えて「--permancent」オプションを付けて設定をしました。「--permancent」オプションを指定すると永続設定をするもののランタイムのほうには設定されません。さっきのコマンドとは逆ですね。従って、最後に「firewall-cmd --reload」を実行して、設定をランタイムのほうに反映させています。
ゾーン、インターフェース、NATポリシーの関係を図示すると、以下のような感じでしょうか。

作成済のNATポリシーの情報を確認する。

作成済のNATポリシーの一覧は以下のコマンドで確認することができます。

# firewall-cmd --permanent --get-policies
allow-host-ipv6 libvirt-routed-in libvirt-routed-out libvirt-to-host natPolicy

ふむふむ。今回作成した「natPolicy」の他にも、デフォルトでいくつかのNATポリシーが存在することが分かります(libvirt-* はKVMの仮想マシンがlibvirtのネットワーク経由で外部にアクセスするためのNATポリシーですね、おそらく..)。

NATポリシーの詳細情報は以下のコマンドで確認することができます(今回作成した「natPolicy」の詳細情報を確認しています)。

# firewall-cmd --permanent --info-policy=natPolicy
natPolicy (active)
priority: -1
target: ACCEPT
ingress-zones: trusted
egress-zones: public
services:
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:

インターネットへのアクセスを確認する。

今回の設定をする前は、ホストbase1からインターネットへの接続はできませんでした。
設定後は、ホストbase0とホームルータがルータとなって、base1からインターネットへのアクセスも可能になりました。
例えば、base1から8.8.8.8(googleのDNSサーバ)へのpingも届いています。

# ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 バイト応答 送信元 8.8.8.8: icmp_seq=1 ttl=57 時間=5.26ミリ秒
64 バイト応答 送信元 8.8.8.8: icmp_seq=2 ttl=57 時間=5.62ミリ秒
64 バイト応答 送信元 8.8.8.8: icmp_seq=3 ttl=57 時間=5.78ミリ秒

base1でPKGをupdateしたときも、パブリックリポジトリにアクセスしてPKGを更新することができました。

# dnf update

ダウンロードサイズの合計: 870 M
これでよろしいですか? [y/N]: y
パッケージのダウンロード:
Rocky Linux 9 - AppStream 163% [====================================================================

Rocky Linux 9 - AppStream 163% [====================================================================
Rocky Linux 9 - BaseOS 163% [========================================================================

完了しました!

firewalldの設定をバックアップするのはどうする?

firewalldの設定をいろいろといじっていて、うまくいかないときに初期の状態に戻したいことがあるかと思います。そんなときは、設定を保存する前に /etc/firewalld/ 配下をまるごとバックアップしくのが良いと思います。そうすれば、失敗したら元に戻すことができますので(もちろん戻した後で、firewalldを再起動する必要があります)。設定に自信がない場合は「--permanent」オプションは付けずに設定を行って、動作を確認した後に「firewall-cmd --runtime-to-permanent」で永続化(保存)するという手順をとりたいところですが、実は「firewall-cmd --policy=natPolicy --set-target ACCEPT」を実行したときに「Option can be used only with --permanent.」のエラーになりました。なので今回は、/etc/firewalld/配下をバックアップする方法を選択しましょう。

ところで、ネットワークインターフェースをどのゾーンに所属させるかという設定は、/etc/firewalld配下のファイルには記録されておらず、/etc/NetworkManager/system-connections/<コネクション名>.nmconnection のほうに記録されます。

広告主へのリンク

オイラが今回のテストに使っているのは、高価なサーバではなくて、安価なミニPC MINISFORUM GK41 というマシンです。LANポートが2つ付いているので、PXEブートのテストにも便利です。


更に、このMINISFORUM GK41のUSBポートに以下のUSB-LAN変換アダプタを付けて、LANポートを合計3つにして運用しています。




このブログにおける関連リンク

犬でも分かるLinuxネットワーク
犬でも分かるLinuxネットワーク設定(1): nmcliコマンドの使い方
犬でも分かるLinuxネットワーク設定(2): ボンディング(bonding)
犬でも分かるLinuxネットワーク設定(3): 仮想ブリッジ
犬でも分かるLinuxネットワーク設定(4): ボンディング+仮想ブリッジ
犬でも分かるLinuxネットワーク設定(5):定義ファイルの修正
犬でも分かるLinuxネットワーク設定(6): ルーティングとNAT
犬でも分かるLinuxネットワーク設定(7):firewalldによるアクセス制限
犬でも分かるLinuxネットワーク設定(8):VLAN
犬でも分かるLinuxネットワーク設定(9):IPエイリアス
犬でも分かるLinuxネットワーク設定(10):outboundのアクセス制限
犬でも分かるLinuxネットワーク設定(11):NATポリシーにアクセス制限を設定する

コメント

タイトルとURLをコピーしました