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

今回はサーバー構築において、最も大事な部分であるファイアウォールの設定をしていきます。
ファイアウォールの設定方針
以前までは 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/admindefine 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スクリプトは下記のサイトを参考に作成しました。

パーミッションを変更し、スクリプトを実行すると、リストが作成されています。
chmod 700 nftables_domestic.sh
sh nftables_domestic.sh
ls /etc/nftables/list
(out) admin domesticnftables のテーブルを作成
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 を導入しない方には不要な設定です。適宜調整してください。
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 filternftables のルールセットを表示します。
# 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 です。

※繰り返しアタックしてくる再犯者をブロックする設定(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.targetfail2ban を起動する
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以上で最低限のファイアウォールの設定は一旦完了です。
定期的にログを確認し、ルールの見直しや調整を行ってください。
次の記事

コメント