【Rocky Linux 9】03.firewalld

## firewalld設定
### firewalld設定スクリプト作成
```shell-session:/etc/firewalld/firewall.sh
#!/bin/bash

#---------------------------------------#
# 設定開始                              #
#---------------------------------------#

# 内部ネットワークアドレス定義
LOCALNET=10.10.10.0/24

#---------------------------------------#
# 設定終了                              #
#---------------------------------------#

#
# ファイアウォール設定初期化
#
systemctl stop firewalld
rm -f /etc/firewalld/zones/*
rm -f /etc/firewalld/ipsets/*
systemctl start firewalld
firewall-cmd --reload >/dev/null

#
# 内部からのアクセスを許可
#
firewall-cmd --add-rich-rule="rule family="ipv4" source address="10.0.0.0/8" accept" --permanent >/dev/null
firewall-cmd --add-rich-rule="rule family="ipv4" source address="172.16.0.0/12" accept" --permanent >/dev/null
firewall-cmd --add-rich-rule="rule family="ipv4" source address="192.168.0.0/16" accept" --permanent >/dev/null
firewall-cmd --add-rich-rule="rule family="ipv4" source address="${LOCALNET}" accept" --permanent >/dev/null

#
# SYN Cookiesを有効にする
# ※TCP SYN Flood攻撃対策
#
sysctl -w net.ipv4.tcp_syncookies=1 > /dev/null
sed -i '/net.ipv4.tcp_syncookies/d' /etc/sysctl.conf
echo "net.ipv4.tcp_syncookies=1" >> /etc/sysctl.conf

#
# ブロードキャストアドレス宛pingには応答しない
# ※Smurf攻撃対策
#
sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1 > /dev/null
sed -i '/net.ipv4.icmp_echo_ignore_broadcasts/d' /etc/sysctl.conf
echo "net.ipv4.icmp_echo_ignore_broadcasts=1" >> /etc/sysctl.conf

#
# ICMP Redirectパケットは拒否
#
sed -i '/net.ipv4.conf.*.accept_redirects/d' /etc/sysctl.conf
for dev in `ls /proc/sys/net/ipv4/conf/`
do
    sysctl -w net.ipv4.conf.$dev.accept_redirects=0 > /dev/null
    echo "net.ipv4.conf.$dev.accept_redirects=0" >> /etc/sysctl.conf
done

#
# Source Routedパケットは拒否
#
sed -i '/net.ipv4.conf.*.accept_source_route/d' /etc/sysctl.conf
for dev in `ls /proc/sys/net/ipv4/conf/`
do
    sysctl -w net.ipv4.conf.$dev.accept_source_route=0 > /dev/null
    echo "net.ipv4.conf.$dev.accept_source_route=0" >> /etc/sysctl.conf
done

#
# IPアドレスリスト取得
#
IP_LIST=/etc/firewalld/tmp/cidr.txt
CHK_IP_LIST=/etc/firewalld/tmp/IPLIST
if [ ! -f ${IP_LIST} ]; then
    wget -q http://nami.jp/ipv4bycc/cidr.txt.gz
    gunzip -c cidr.txt.gz > ${IP_LIST}
    rm -f cidr.txt.gz
fi
rm -f ${CHK_IP_LIST}


#
# ゾーン(日本国内)作成
#

# domestic(日本国内)ゾーン作成
firewall-cmd --new-zone=domestic --permanent >/dev/null

# domestic(日本国内)IPセット作成
firewall-cmd --new-ipset=domestic --type=hash:net --permanent >/dev/null

# 日本国内のIPアドレスリスト作成
domestic_ipset=`mktemp`
for addr in `cat ${IP_LIST} | grep ^JP | awk '{print $2}'`
do
    echo ${addr} >> ${domestic_ipset}
done

# 日本国内のIPアドレスリストをdomestic(日本国内)IPセットに登録
firewall-cmd --ipset=domestic --add-entries-from-file=${domestic_ipset} --permanent >/dev/null
rm -f ${domestic_ipset}

# domestic(日本国内)IPセットをdomestic(日本国内)ゾーンに登録
firewall-cmd --zone=domestic --add-source=ipset:domestic --permanent >/dev/null

# IPアドレス更新チェック用に退避
grep ^JP ${IP_LIST} >> $CHK_IP_LIST

# 以降,日本国内からのみアクセスを許可したい場合はdomesticゾーンにサービスを追加する

# 全国警察施設への攻撃元上位５カ国(日本・アメリカを除く)からのアクセスを破棄
# 直近１週間の状況 http://www.npa.go.jp/cyberpolice/detect/observation.html
# 前月の状況 http://www.npa.go.jp/cyberpolice/detect/index.html
# 国コード一覧 https://ja.wikipedia.org/wiki/ISO_3166-1#%E7%95%A5%E5%8F%B7%E4%B8%80%E8%A6%A7
DROP_COUNTRY_LIST=(BG HK RO CN GB)

# drop_country(アクセス禁止国)IPセット作成
firewall-cmd --new-ipset=drop_country --type=hash:net --permanent >/dev/null

# アクセス禁止国のIPアドレスリスト作成
drop_ipset=`mktemp`
for country in "${DROP_COUNTRY_LIST[@]}"
do
    for addr in `cat ${IP_LIST} | grep ^${country} | awk '{print $2}'`
    do
        echo ${addr} >> ${drop_ipset}
    done
    grep ^${country} ${IP_LIST} >> ${CHK_IP_LIST}
done

# アクセス禁止国のIPアドレスリストをdrop_country(アクセス禁止国)IPセットに登録
firewall-cmd --ipset=drop_country --add-entries-from-file=${drop_ipset} --permanent >/dev/null
rm -f ${drop_ipset}

# drop_country(アクセス禁止国)IPセットをdropゾーンに登録
firewall-cmd --zone=drop --add-source=ipset:drop_country --permanent >/dev/null

#----------------------------------------------------------#
# 各種サービスを公開する場合の設定(ここから)               #
#----------------------------------------------------------#

# 不要なポート開放を拒否
firewall-cmd --remove-service=dhcpv6-client --zone=public --permanent > /dev/null
firewall-cmd --remove-service=cockpit --zone=public --permanent > /dev/null

# 外部からのSSH(TCP22番ポート)へのアクセスを日本国内からのみ許可
# ※SSHサーバーを公開する場合のみ
firewall-cmd --remove-service=ssh --zone=public --permanent >/dev/null
firewall-cmd --add-service=ssh --zone=domestic --permanent >/dev/null

# 外部からのDNS(TCP/UDP53番ポート)へのアクセスを許可
# ※外部向けDNSサーバーを運用する場合のみ
firewall-cmd --add-service=dns --zone=public --permanent >/dev/null
firewall-cmd --add-service=dns --zone=domestic --permanent >/dev/null

# 外部からのHTTP(TCP80番ポート)へのアクセスを許可
# ※Webサーバーを公開する場合のみ
firewall-cmd --add-service=http --zone=public --permanent >/dev/null
firewall-cmd --add-service=http --zone=domestic --permanent >/dev/null

# 外部からのHTTPS(TCP443番ポート)へのアクセスを許可
# ※Webサーバーを公開する場合のみ
firewall-cmd --add-service=https --zone=public --permanent >/dev/null
firewall-cmd --add-service=https --zone=domestic --permanent >/dev/null

# 外部からのSMTP(TCP25番ポート)へのアクセスを許可
# ※SMTPサーバーを公開する場合のみ
firewall-cmd --add-service=smtp --zone=public --permanent >/dev/null
firewall-cmd --add-service=smtp --zone=domestic --permanent >/dev/null

# 外部からのSUBMISSION(TCP587番ポート)へのアクセスを日本国内からのみ許可
# ※SMTPサーバーを公開する場合のみ
# ※SMTPSサーバー（TCP465番ポート）を公開する場合は不要
firewall-cmd --add-service=smtp-submission --zone=domestic --permanent >/dev/null

# 外部からのSMTPS(TCP465番ポート)へのアクセスを日本国内からのみ許可
# ※SMTPSサーバーを公開する場合のみ 2>&1
firewall-cmd --add-service=smtps --zone=domestic --permanent >/dev/null

# 外部からのPOP3(TCP110番ポート)へのアクセスを日本国内からのみ許可
# ※POP3サーバーを公開する場合のみ
firewall-cmd --add-service=pop3 --zone=domestic --permanent >/dev/null

# 外部からのPOP3S(TCP995番ポート)へのアクセスを日本国内からのみ許可
# ※POP3Sサーバーを公開する場合のみ
firewall-cmd --add-service=pop3s --zone=domestic --permanent >/dev/null

# 外部からのIMAP(TCP143番ポート)へのアクセスを日本国内からのみ許可
# ※IMAPサーバーを公開する場合のみ
firewall-cmd --add-service=imap --zone=domestic --permanent >/dev/null

# 外部からのIMAPS(TCP993番ポート)へのアクセスを日本国内からのみ許可
# ※IMAPSサーバーを公開する場合のみ
firewall-cmd --add-service=imaps --zone=domestic --permanent >/dev/null

#----------------------------------------------------------#
# 各種サービスを公開する場合の設定(ここまで)               #
#----------------------------------------------------------#

# 拒否IPアドレスからのアクセスはログを記録せずに破棄
# ※拒否IPアドレスは/etc/firewalld/deny_ipに1行ごとに記述しておくこと
# (/etc/firewalld/deny_ipがなければなにもしない)
if [ -s /etc/firewalld/deny_ip ]; then
    for ip in `cat /etc/firewalld/deny_ip`
    do
        firewall-cmd --zone=drop --permanent --add-source=${ip} --permanent >/dev/null
    done
fi

# ファイアウォール設定反映
firewall-cmd --reload >/dev/null
```

### IPアドレスリスト更新チェックスクリプト作成
```shell-session:/etc/cron.daily/iplist_check.sh
#!/bin/bash

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# 新旧IPLIST差分チェック件数(0を指定するとチェックしない)
# ※新旧IPLIST差分がSABUN_CHKで指定した件数を越える場合はfirewall設定スクリプトを実行しない
# ※新旧IPLIST差分チェック理由はhttp://centossrv.com/bbshtml/webpatio/1592.shtmlを参照
SABUN_CHK=100
[ $# -ne 0 ] && SABUN_CHK=${1}

# IPアドレスリスト取得
IP_LIST=/etc/firewalld/tmp/cidr.txt
CHK_IP_LIST=/etc/firewalld/tmp/IPLIST
wget -q http://nami.jp/ipv4bycc/cidr.txt.gz
gunzip -c cidr.txt.gz > $IP_LIST
rm -f cidr.txt.gz

# チェック対象IPアドレスリスト最新化
rm -f IPLIST.new
for country in `awk '{print $1}' $CHK_IP_LIST |uniq`
do
    grep ^$country $IP_LIST >> IPLIST.new
done

# チェック対象IPアドレスリスト更新チェック
diff -q $CHK_IP_LIST IPLIST.new > /dev/null 2>&1
if [ $? -ne 0 ]; then
    if [ ${SABUN_CHK} -ne 0 ]; then
        if [ $(diff $CHK_IP_LIST IPLIST.new | egrep -c '<|>') -gt ${SABUN_CHK} ]; then
            (
             diff $CHK_IP_LIST IPLIST.new
             echo
             echo "firewall.sh not executed."
            ) | mail -s 'IPLIST UPDATE' root
            rm -f IPLIST.new
            exit
        fi
    fi
    /bin/mv IPLIST.new $CHK_IP_LIST
    /bin/bash /etc/firewalld/firewall.sh > /dev/null
else
    rm -f IPLIST.new
fi
```

### firewalld初回設定
```shell-session
mkdir /etc/firewalld/tmp
chmod +x /etc/firewalld/firewall.sh
chmod +x /etc/cron.daily/iplist_check.sh
```

### firewalld初回起動
```shell-session
/etc/cron.daily/iplist_check.sh
/etc/firewalld/firewall.sh
systemctl enable --now firewalld
```

## 参考サイト
https://centossrv.com/almalinux/firewall.shtml