Red Hat Enterprise Linux 9 のファイアウォール(nftables)設定

ConoHa Enterprise Linux 9
このサイトはアフィリエイト広告(Amazonアソシエイト含む)を掲載しています。
スポンサーリンク

ここまで ConoHa の VPS に RHEL9 をインストールする方法と、初期設定の解説をしてきました。

Red Hat Enterprise Linux 9 の初期設定
前回の記事で ConoHa の VPS に RHEL9 をインストールする手順を説明しましたが、今回はこれに基本的な設定を施していきます。SELinux の無効化当初の予定では SELinux を有効にしたまま運用する気だったのだが、いきな...

今回はサーバー構築において、最も大事な部分であるファイアウォールの設定をしていきます。

ConoHa VPS

ファイアウォールの設定方針

以前までは firewalld を使用した ipset でアクセスの可否をリスト管理していましたが、RHEL9 から ipset が廃止になったという事なので nftables で運用していきます。

IP アドレスのリストは、管理者用(admin)と、日本国内(domestic)の 2 種類を用意し、下記の方針で設定します。

  • 管理者のみアクセス可能:ssh, 後からインストールする予定の OLS 管理画面(TCP 7080)
  • 日本国内からのみアクセス可能:SMTPS, IMAPS
  • IP アドレスによる制限なし:HTTP, HTTPS, SMTP

また fail2ban を導入し、アクセスログに残された不正アクセスの痕跡をもとに、自動的に遮断するように設定します。

nftables の設定

nftables のインストール

RHEL9 や CentOS Stream 9 では最初から nftables が組み込まれていますが、AlmaLinux 9 や Rocky Linux 9 の場合は入っていないので、インストールから行ってください。

dnf install nftables

管理者用の IP アドレスリストを作成

nftables の設定ファイルは /etc/nftables にありますが、ここにリスト用のディレクトリ(list)を作成します。そして、その中に管理者用の IP アドレスリスト(admin)を作成します。

mkdir /etc/nftables/list
vi /etc/nftables/list/admin
define admin = {
        198.51.100.21,  # 自宅
        203.0.113.1     # 会社
}

admin を定義し、自宅と職場の IP アドレスを登録しました。

※コメントはアドレスと同じ行の後ろに書く分には問題ありませんが、コメントだけの行にしてしまうとエラーになります。

日本国内の IP アドレスリストを作成

次に、日本国内に配布されている IPv4 アドレスの表からリスト(domestic)を作成します。

#!/usr/bin/bash

LIST=/etc/nftables/list/domestic

mkdir -p /etc/nftables/list
cd /etc/nftables/list
wget http://nami.jp/ipv4bycc/cidr.txt.gz
gunzip cidr.txt.gz
echo "define domestic = {" > ${LIST}
for COUNTRY in 'JP'
do
    sed -n "s/^JP\t//p" cidr.txt | while read ADDRESS
    do
        echo "        ${ADDRESS}," >> ${LIST}
    done
done
echo "}" >> ${LIST}
rm cidr.txt

スクリプトは下記のサイトを参考に作成しました。

nftablesでSSHを日本国内からの接続に限定する (CentOS 8)
はじめに以前、国別のIPアドレスリストを利用して、CentOS 7で、ipset と iptables で SSH を日本国内からの接続に限定する設定方法をまとめました。・ipsetとiptablesでSSHを日本国内からの接続に限定する ...

パーミッションを変更し、スクリプトを実行すると、リストが作成されています。

chmod 700 nftables_domestic.sh
sh nftables_domestic.sh
ls /etc/nftables/list
(out) admin  domestic

nftables のテーブルを作成

nftables のテーブルファイル(/etc/nftables/filter.nft)を新規に作成します。

# 現在のルールセットを消去
flush ruleset

# 管理者用IPアドレスリストを読み込む
include "/etc/nftables/list/admin"
# 日本国内IPアドレスリストを読み込む
include "/etc/nftables/list/domestic"

table inet filter {

        set admin {
                type ipv4_addr
                elements = $admin
        }

        set domestic {
                type ipv4_addr
                flags interval
                elements = $domestic
        }

        chain input {
                type filter hook input priority 0; policy drop;

                # Ping floods
                ip protocol icmp icmp type echo-request limit rate 10/second accept

                # 関連・確立済みトラフィックは許可する
                ct state established,related accept

                # 不正なトラフィックは全て破棄する
                ct state invalid drop

                # ループバックインターフェイスのトラフィックは全て許可する
                iif lo accept

                # 新しいエコー要求 (ping) は許可する
                ip protocol icmp icmp type echo-request ct state new accept

                ip protocol udp ct state new jump UDP
                ip protocol tcp tcp flags & (fin | syn | rst | ack) == syn ct state new jump TCP

                # 他のルールによって処理されなかったトラフィックは全て拒否する
                ip protocol udp reject
                ip protocol tcp reject with tcp reset
        }

        chain forward {
                type filter hook forward priority 0; policy drop;
        }

        chain output {
                type filter hook output priority 0; policy accept;
        }

        chain TCP {
                # 管理者にのみ解放
                # ssh, OLS 管理画面
                tcp dport { 22, 7080 } ip saddr @admin accept

                # 日本国内にのみ開放
                # SMTPS, IMAPS
                tcp dport { 465, 993 } ip saddr @domestic accept

                # 全開放
                # SMTP, HTTP, HTTPS
                tcp dport { 25, 80, 443 } accept
        }

        chain UDP {
                # 全開放
                # http/3
                #udp dport { 443 } accept
        }

}

※管理者のみに開放している 7080 ポートは、OpenLiteSpeed を導入しない方には不要な設定です。適宜調整してください。

nftables - ArchWiki

filter.nft を読み込む

nftables の設定ファイル(/etc/sysconfig/nftables.conf)を修正して、filter.nft を読み込むようにします。

#include "/etc/nftables/main.nft"
include "/etc/nftables/filter.nft"

サービスの起動

まず、現在動いている firewalld の停止と、自動起動を解除する。

systemctl stop firewalld.service
systemctl disable firewalld.service

次に、nftables の起動と、自動起動を設定する。

systemctl start nftables.service
systemctl enable nftables.service
(out) Created symlink /etc/systemd/system/multi-user.target.wants/nftables.service → /usr/lib/systemd/system/nftables.service.

テーブルの確認

nftables のテーブル一覧を表示します。

nft list tables
(out) table inet filter

nftables のルールセットを表示します。

# nft list ruleset
table inet filter {
        set admin {
                type ipv4_addr
                elements = { 198.51.100.21, 203.0.113.1 }
        }

        set domestic {
                type ipv4_addr
                flags interval
                elements = { 1.0.16.0/20, 1.0.64.0/18,

                             ...

                             223.252.64.0/19, 223.252.112.0/20 }
        }

        chain input {
                type filter hook input priority filter; policy drop;
                ip protocol icmp icmp type echo-request limit rate 4/second accept
                ct state established,related accept
                iif "lo" accept
                ct state invalid drop
                ip protocol icmp icmp type echo-request ct state new accept
                ip protocol udp ct state new jump UDP
                ip protocol tcp tcp flags & (fin | syn | rst | ack) == syn ct state new jump TCP
                ip protocol udp reject
                ip protocol tcp reject with tcp reset
                meta nfproto ipv4 counter packets 0 bytes 0 reject with icmp type prot-unreachable
        }

        chain forward {
                type filter hook forward priority filter; policy drop;
        }

        chain output {
                type filter hook output priority filter; policy accept;
        }

        chain TCP {
                tcp dport { 22, 7080 } ip saddr @admin accept
                tcp dport { 465, 993 } ip saddr @domestic accept
                tcp dport { 25, 80, 443 } accept
        }

        chain UDP {
        }
}

先ほど作成した filter.nft に、admin と domestic の IP アドレスリストが反映されていることが確認できました。

fail2ban の設定

fail2ban のインストール

アクセスログから不審なログインを監視する fail2ban をインストールする。

dnf install fail2ban whois

※whois コマンドは入れなくても動きますが、Ban した際にメールで Whois 情報を送る場合は必要になります。

設定ファイルを作成

設定ファイルを直接編集するのではなく、jail.local ファイルを作成してオーバーライドさせます。

vi /etc/fail2ban/jail.local

連携先をiptables から nftables に変更します。

[DEFAULT]
# nftables を使用
banaction = nftables-multiport
banaction_allports = nftables-allports
# 試行回数
maxretry = 3
# 監視スパン
findtime = 1h
# 隔離時間
bantime = 1d
# アラートメールの通知先
destemail = root@example.com
# アラートメールの送信元
sender = fail2ban@example.com
# BANしてWhois情報とログ情報をメール通知
action = %(action_mwl)s
# 除外リスト(半角スペース区切り)
ignoreip = 198.51.100.21 203.0.113.1 

[sshd]
enabled = true

[recidive]
enabled = true

標準の設定ファイル(/etc/fail2ban/jail.conf)に対して、上書きしたい部分だけを記述すれば OK です。

Fail2Banを使って不正なアクセスを遮断する(全自動)
Fail2BanFail2Banはログを監視し、おかしなアクセスがあったらBAN、指定時間を過ぎたらUNBANを自動で実行してくれるツールです。Fail2Ban自体に遮断する機能はありませんが、iptablesやfirewalldと連携して...

※繰り返しアタックしてくる再犯者をブロックする設定(recidive)を最初から入れると fail2ban の設定エラーになる場合がありました。その場合は recidive の設定は外して運用し、後述する f2b-table が作られてから追加すると上手くいきました。

起動オプションを修正

起動時のオプションを確認すると firewalld を呼ぶようになっているので、ここも修正していきます。

systemctl edit fail2ban.service

設定を上書きしたい部分だけを記入して保存します。

### Editing /etc/systemd/system/fail2ban.service.d/override.conf
### Anything between here and the comment below will become the new contents of the file

[Unit]
Requires=nftables.service
PartOf=nftables.service

[Install]
WantedBy=multi-user.target nftables.service

### Lines below this comment will be discarded

### /etc/systemd/system/fail2ban.service
# [Unit]
# Description=Fail2Ban Service
# Documentation=man:fail2ban(1)
# After=network.target iptables.service firewalld.service ip6tables.service ipset.service nftables.service
# PartOf=firewalld.service
#
# [Service]
# Type=simple
# Environment="PYTHONNOUSERSITE=1"
# ExecStartPre=/bin/mkdir -p /run/fail2ban
# ExecStart=/usr/bin/fail2ban-server -xf start
# # if should be logged in systemd journal, use following line or set logtarget to sysout in fail2ban.local
# # ExecStart=/usr/bin/fail2ban-server -xf --logtarget=sysout start
# ExecStop=/usr/bin/fail2ban-client stop
# ExecReload=/usr/bin/fail2ban-client reload
# PIDFile=/run/fail2ban/fail2ban.pid
# Restart=on-failure
# RestartPreventExitStatus=0 255
#
# [Install]
# WantedBy=multi-user.target
Using systemd to bind fail2ban to nftables < System | The Art of Web
Systemd configuration instructions for binding fail2ban.service so it starts, stops and restarts with nftables.service.

fail2ban を起動する

systemctl start fail2ban.service
systemctl enable fail2ban.service
(out) Created symlink /etc/systemd/system/multi-user.target.wants/fail2ban.service → /etc/systemd/system/fail2ban.service.
(out) Created symlink /etc/systemd/system/nftables.service.wants/fail2ban.service → /etc/systemd/system/fail2ban.service.

動作確認

nftables に f2b-table のテーブルが追加されたことを確認します。

nft list tables
(out) table inet filter
(out) table inet f2b-table

確認のため、一時的に ssh のポートを全開放に変更。暫く経ってから確認したところ、ssh への侵入をブロックした形跡が確認できた。

nft list table inet f2b-table
(out) table inet f2b-table {
(out)         set addr-set-sshd {
(out)                 type ipv4_addr
(out)                 elements = { 203.0.113.214, 192.0.2.112,
(out)                              198.51.100.115, 203.0.113.42,
(out)                              198.51.100.164, 192.0.2.22 }
(out)         }
(out) 
(out)         set addr-set-recidive {
(out)                 type ipv4_addr
(out)                 elements = { 203.0.113.36, 198.51.100.140 }
(out)         }
(out) 
(out)         chain f2b-chain {
(out)                 type filter hook input priority filter - 1; policy accept;
(out)                 tcp dport { 22 } ip saddr @addr-set-sshd reject
(out)                 meta l4proto { tcp } ip saddr @addr-set-recidive reject
(out)         }
(out) }

fail2ban 側のステータスも出力して、nftables と同じ内容であることが確認できました。

fail2ban-client status | sed -n 's/,//g;s/.*Jail list://p' | xargs -n1 fail2ban-client status
(out) Status for the jail: recidive
(out) |- Filter
(out) |  |- Currently failed: 0
(out) |  |- Total failed:     0
(out) |  `- File list:        /var/log/fail2ban.log
(out) `- Actions
(out)    |- Currently banned: 2
(out)    |- Total banned:     2
(out)    `- Banned IP list:   198.51.100.140 203.0.113.36
(out) Status for the jail: sshd
(out) |- Filter
(out) |  |- Currently failed: 0
(out) |  |- Total failed:     0
(out) |  `- Journal matches:  _SYSTEMD_UNIT=sshd.service + _COMM=sshd
(out) `- Actions
(out)    |- Currently banned: 6
(out)    |- Total banned:     6
(out)    `- Banned IP list:   192.0.2.22 192.0.2.112 198.51.100.115 198.51.100.164 203.0.113.42 203.0.113.214

以上で最低限のファイアウォールの設定は一旦完了です。

定期的にログを確認し、ルールの見直しや調整を行ってください。

ConoHa VPS

次の記事

Red Hat Enterprise Linix 9 に http/3 対応のウェブサーバー(OpenLiteSpeed)を構築する
前回からだいぶ間が空いてしまいましたが、ConoHa の VPS にインストールした RHEL9 上にウェブサーバーを導入していきます。ちょうど最近 OpenLiteSpeed のリポジトリに CentOS 9 用が追加されていましたので、...

コメント

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