初めに #
サーバーをインターネットに公開すると、常に外部からのアクセスに晒されることになります。
特に SSH や FTP などのリモート接続サービスは、不正ログインやブルートフォース攻撃の対象となりやすく、大半の攻撃は海外IPアドレスから行われるのが一般的です。
これは攻撃者が身元特定を避けるため、匿名性の高い回線やボットネットを利用するケースが多いためです。
そのため、特定のサービスへの接続を日本国内のIPアドレスに限定することは、非常に効果的なセキュリティ対策となります。
IP制限は不要な攻撃トラフィックを大幅に削減でき、その他のセキュリティ対策と組み合わせることで、より安全な運用が可能になります。
Linux では、firewalld というファイアウォール管理ツールを利用することで、特定の国のIPアドレスのみを許可したり、制限したりする設定を簡単に行うことができます。
そこで本記事では、AlmaLinux 9 環境で firewalld を利用し、日本国内のIPアドレスからのアクセスのみを許可する方法を初心者でも分かりやすく解説します。
インストール確認 #
初めに firewalld が既にシステムにインストールされているか確認を行います。
以下のように rpm コマンドを実行することで、関連パッケージがインストール済みかどうかを確認できます。
# rpm -qa |grep "firewalld"
firewalld-filesystem-1.3.4-15.el9_6.noarch
firewalld-1.3.4-15.el9_6.noarch
このように firewalld 本体と firewalld-filesystem が表示されれば、インストールは完了となっています。
まだインストールされていない場合は、以下のコマンドにて導入を行なってください。
dnf install firewalld
IPセットとは #
今回は、firewalldのアクセス制御に ipset(IPアドレスセット) 機能を利用します。
通常、ファイアウォールで特定の国のIPアドレスだけを許可したり拒否したりする場合、その国に割り当てられた大量のIPアドレス範囲を個別にルールとして追加する必要があり、非常に手間がかかります。
ipset を利用することで、複数のIPアドレスやネットワークアドレスの集合を ファイアウォール上で1つのグループとして管理することができます。
日本に割り当てられたIPアドレスのリストは、インフラ技術部にて公開している ip-databank-v4 リポジトリのデータを利用します。
IPv4アドレスの割当情報を国別に分類したデータを公開するリポジトリです
それでは実際に設定を進めていきましょう。
IPセットの作成 #
まずは firewalld にて日本向けのIPセットを作成し、日本のIPアドレス範囲をその中に登録します。
リストの定義 #
はじめに、firewalld コマンドを利用して新しいIPセットを作成します。
名前は japan とし、タイプはネットワークアドレスを扱える hash:net を指定します。
また --permanent オプションを付けることで設定を恒久化し、再起動後も設定が残るようにします。
firewall-cmd --permanent --new-ipset=japan --type=hash:net
コマンドの実行結果が success と表示されれば作成成功となります。
IPアドレスリストの取得 #
次に、日本国内のIPアドレス範囲リストを取得します。
GitHub上の ip-databank-v4 リポジトリに、日本に割り当てられたIPv4アドレスのCIDRブロック一覧が公開されています。
curl コマンドを利用しリストをダウンロードします。
curl -sSL https://raw.githubusercontent.com/r1999-jp/ip-databank-v4/refs/heads/main/data/jp.txt \
> /etc/firewalld/ipsets/japan.txt
ダウンロードしたリストは /etc/firewalld/ipsets/japan.txt というファイルに保存されます。
コマンドの実行が完了したら、japan.txt に日本のIPv4ネットワークアドレス(CIDR表記)がずらりと書き込まれているはずです。
ファイルから一括追加 #
次に先ほど取得した japan.txt を利用し、IPセット japan にIPアドレス範囲を登録します。
firewalld には、ファイルにまとめられた複数のIPアドレスを一括で登録できる機能が用意されています。
一括で登録を行うには以下のように セット名 と ファイルパス を指定し firewalld のコマンドを実行する必要があります。
firewall-cmd --permanent --ipset=<セット名> --add-entries-from-file=<ファイルパス>
今回はセット名が japan 、 ファイルパスが /etc/firewalld/ipsets/japan.txt となっております。
そのため以下のようにコマンドを実行してください。
firewall-cmd --permanent --ipset=japan --add-entries-from-file=/etc/firewalld/ipsets/japan.txt
このコマンドにより、japan.txt に含まれる全てのネットワークアドレスが IPセット japan に登録されます。
先ほどと同様に実行結果に success と表示されれば、問題なくIPセットへの登録が完了しています。
リロード #
IPセットへの登録が完了したら firewalld をリロードして新しい設定を反映させます。
リロードにより、先ほど作成したIPセット japan とそのエントリが実際のファイアウォールルールで利用可能な状態になります。
firewall-cmd --reload
上記コマンド実行後に success と表示されれば、リロード完了となります。
エラーとなる場合は設定に誤りがある可能性があります。
エラー内容を確認し該当箇所の設定を見直してください。
登録確認 #
リロードが完了したらIPセット japan が実際に正しく登録されているか確認してみましょう。
以下のコマンドにて指定したIPセットの情報を確認することができます。
firewall-cmd --info-ipset=japan
上記を実行すると以下のようにIPセット japan の情報が表示されます。
エラーがなく表示されていれば、登録は正常に完了しています。
表示内容にはタイプ(hash:net)や登録内容が含まれております。
japan
type: hash:net
options:
entries: 1.0.16.0/20 1.0.64.0/18 1.1.64.0/18 1.5.0.0/16 1.21.0.0/18 1.21.64.0/19 1.21.96.0/20 1.21.112.0/20 1.21.128.0/20 1.21.144.0/20
ルールの適用 #
IPセットの準備ができたので、このIPセットを利用し制限ルールを設定します。
今回は例として SSH サービスに制限をかける手順をご紹介します。
サービス名を置き換えることにより他サービスに適用することも可能です。
必要に応じて置き換えを実施してください。
既存の SSH 許可設定を削除 #
初めに現在の firewalld 設定から SSH サービスの許可ルールを削除します。
AlmaLinux を含む多くの RedHat 系ディストリビューションでは、デフォルトで ssh サービスが自動的に許可されています。
これはつまり、全世界から SSH 接続を受け付ける状態になっているということです。
そのため、まずは既存の許可ルールを削除し、後のステップで 日本国内のIPアドレスだけを許可する設定を行っていきます。
firewall-cmd --permanent --zone=public --remove-service=ssh
上記コマンドで、public ゾーンから SSH サービスの許可が削除されました。
success と出れば削除成功です。
この時点では、実行中の firewalld 設定には反映されていませんが、次にリロードすれば SSH は許可されない状態になります。
日本だけ許可するリッチルールを追加 #
続いて、SSH を許可する条件として「接続元が日本のIPセットに含まれる場合のみ許可」というルールを追加します。
ここではリッチルールを利用して、source(送信元)にIPセット japan を指定した許可ルールを設定します。
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source ipset="japan" service name="ssh" accept'
上記コマンドにより、送信元がIPセット japan 内のアドレスで、サービスが ssh なら受け入れるというルールが追加されました。
このコマンドも実行後に success と表示されれば成功です。
リロード #
新たに追加したリッチルールを有効化するため、再度 firewalld をリロードします。
先ほど削除した SSH 許可設定と、今回追加した日本限定の許可ルールの両方がここで反映されます。
firewall-cmd --reload
これで設定変更が実際のファイアウォールに適用されました。
適用確認 #
最後に、意図した通りの設定になっているかを確認します。
まず現在許可されているサービス一覧を表示し、SSH が含まれていないことを確認します。
$ firewall-cmd --list-services
cockpit dhcpv6-client
上記のように、許可サービス一覧に ssh が表示されなければ成功です。
今回の例では cockpit と dhcpv6-client のみだけが表示されており、SSH は含まれていません。
続いて以下のコマンドにてリッチルールの一覧を確認します。
$ firewall-cmd --list-rich-rules
rule family="ipv4" source ipset="japan" service name="ssh" accept
上記のように、日本のIPセット japan をソースとした SSH 許可のリッチルールが表示されていれば成功です。
これにより、日本以外のIPアドレスからの SSH 接続はファイアウォールによってブロックされ、サーバーのセキュリティが大幅に向上します。
初心者の方は手順通り進めれば難しくありませんが、設定を誤ると自分自身がSSH接続できなくなる可能性もあります。
リモートで設定を行っている場合などは、作業中の SSHセッションを維持しつつ別のターミナルでテストを行うなど、慎重に適用を行うことをお勧めします。
必要に応じて他のサービスにも同様の方法でIPセットを使った制限を適用できますので、ぜひ活用してみてください。