Rocky Linux 8(RHEL8 以降)で、firewalldおよびiptablesで特定のリストからのアクセス制限が動作しなくなった(ipsetユーティリティが使えなったのが原因?自分の力量不足?エラーは出ないが思った通りに動作しないので最悪)ので、nftablesでファイアウォールの設定を行いました。
アドレスリストの取得スクリプトの作成
IPアドレスの情報は、以下から入手
・ http://ftp.apnic.net/stats/apnic/delegated-apnic-latest
・ https://ipv4.fetus.jp/ru.txt
ブロックリストは、以下の国のIPアドレスをブロックする。
・CN 中華人民共和国
・KP 北朝鮮
・RU ロシア連邦
・ /etc/nftables/country_list_ipv4 日本国内のIPv4アドレス (make_country_list_ipv4.sh)
・ /etc/nftables/country_list_ipv6 日本国内のIPv6アドレス (make_country_list_ipv6.sh)
・ /etc/nftables/block_list_ipv4 IPv4ブロックリスト (make_block_list_ipv4.sh)
・ /etc/nftables/block_list_ipv6 IPv6ブロックリスト (make_block_list_ipv6.sh)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
#!/bin/bash COUNTRYLIST='JP' LISTSET_FILE=/etc/nftables/country_list_ipv4 rm -fr delegated-apnic-latest wget -q http://ftp.apnic.net/stats/apnic/delegated-apnic-latest echo "define country_list_ipv4 = {" > ${LISTSET_FILE} for country in $COUNTRYLIST do for ip in `cat delegated-apnic-latest | grep "apnic|$country|ipv4|"` do COUNTRY=`echo $ip | awk -F"|" '{ print $2 }'` IPADDR=`echo $ip | awk -F"|" '{ print $4 }'` TMPCIDR=`echo $ip | awk -F"|" '{ print $5 }'` FLTCIDR=32 while [ $TMPCIDR -ne 1 ]; do TMPCIDR=$((TMPCIDR/2)) FLTCIDR=$((FLTCIDR-1)) done echo " $IPADDR/$FLTCIDR," >> ${LISTSET_FILE} done done echo "}" >> ${LISTSET_FILE} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#!/bin/bash COUNTRYLIST='JP' LISTSET_FILE=/etc/nftables/country_list_ipv6 rm -fr delegated-apnic-latest wget -q http://ftp.apnic.net/stats/apnic/delegated-apnic-latest echo "define country_list_ipv6 = {" > ${LISTSET_FILE} for country in $COUNTRYLIST do for ip in `cat delegated-apnic-latest | grep "apnic|$country|ipv6|"` do IPADDR=`echo $ip | awk -F"|" '{ print $4 }'` CIDR=`echo $ip | awk -F"|" '{ print $5 }'` echo " $IPADDR/$CIDR," >> ${LISTSET_FILE} done done echo "}" >> ${LISTSET_FILE} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
#!/bin/bash COUNTRYLIST='CN KP' LISTSET_FILE=/etc/nftables/block_list_ipv4 rm -fr delegated-apnic-latest wget -q http://ftp.apnic.net/stats/apnic/delegated-apnic-latest touch $$ for country in $COUNTRYLIST do for ip in `cat delegated-apnic-latest | grep "apnic|$country|ipv4|"` do COUNTRY=`echo $ip | awk -F"|" '{ print $2 }'` IPADDR=`echo $ip | awk -F"|" '{ print $4 }'` TMPCIDR=`echo $ip | awk -F"|" '{ print $5 }'` FLTCIDR=32 while [ $TMPCIDR -ne 1 ]; do TMPCIDR=$((TMPCIDR/2)) FLTCIDR=$((FLTCIDR-1)) done echo "$IPADDR/$FLTCIDR" >> $$ done done rm -fr ru.txt wget -q https://ipv4.fetus.jp/ru.txt grep "^[0-9]" ru.txt >> $$ echo "define block_list_ipv4 = {" > ${LISTSET_FILE} sort -n $$ | uniq | sed -e 's/^/ /' -e 's/$/,/' >> ${LISTSET_FILE} echo "}" >> ${LISTSET_FILE} rm -fr $$ |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#!/bin/bash COUNTRYLIST='CN KP RU' LISTSET_FILE=/etc/nftables/block_list_ipv6 rm -fr delegated-apnic-latest wget -q http://ftp.apnic.net/stats/apnic/delegated-apnic-latest echo "define block_list_ipv6 = {" > ${LISTSET_FILE} for country in $COUNTRYLIST do for ip in `cat delegated-apnic-latest | grep "apnic|$country|ipv6|"` do IPADDR=`echo $ip | awk -F"|" '{ print $4 }'` CIDR=`echo $ip | awk -F"|" '{ print $5 }'` echo " $IPADDR/$CIDR," >> ${LISTSET_FILE} done done echo "}" >> ${LISTSET_FILE} |
nftables設定ファイルの作成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
#!/usr/sbin/nft -f # drop any existing nftables ruleset flush ruleset include "/etc/nftables/country_list_ipv4" include "/etc/nftables/country_list_ipv6" include "/etc/nftables/block_list_ipv4" include "/etc/nftables/block_list_ipv6" table inet filter { set country_list_ipv4 { type ipv4_addr; flags interval; elements = { $country_list_ipv4 } } set country_list_ipv6 { type ipv6_addr; flags interval; elements = { $country_list_ipv6 } } set block_list_ipv4 { type ipv4_addr; flags interval; elements = { $block_list_ipv4 } } set block_list_ipv6 { type ipv6_addr; flags interval; elements = { $block_list_ipv6 } } chain input { type filter hook input priority 0; policy drop; # allow established/related connections ct state { established, related } accept # early drop of invalid connections ct state invalid drop # allow from loopback iif "lo" accept # allow icmp ip protocol icmp icmp type { echo-request, echo-reply } accept ip6 nexthdr icmpv6 icmpv6 type { echo-request, echo-reply, nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } accept # reject ip(ipv6) addresses pooled ip saddr @block_list_ipv4 reject ip6 saddr @block_list_ipv6 reject # allow smtp, http, https tcp dport { 25, 80, 443 } accept # allow ssh from country_list ip saddr @country_list_ipv4 tcp dport 22 accept ip6 saddr @country_list_ipv6 tcp dport 22 accept # THIS IS THE BROKEN PART #log prefix "nftables-drop(OtherPort): " flags all drop } chain FORWARD { type filter hook forward priority 0; policy drop; } chain OUTPUT { type filter hook output priority 0; policy accept; } } |
(注意事項)
・ IPブロックリストからの接続は、すべて拒否
・ smtp(25)、http(80)、https(443)は、すべてのIPアドレスから接続許可
・ ssh(22)は、国内のIPアドレスからのみアクセス許可
(IPアドレスでの個別設定例)
ip saddr 192.168.1.0/24 tcp dport 22 accept (accept、drop、reject)
ip saddr 192.168.1.0/24 accept (accept、drop、reject)
ip6 saddr N:N:N:N:N:N:N:N/128 tcp dport 22 accept (accept、drop、reject)
ip6 saddr N:N:N:N:N:N:N:N/128 accept (accept、drop、reject)
nftablesパッケージの起動&確認方法
1 2 3 4 5 6 7 |
systemctl stop firewalld systemctl disable firewalld systemctl enable nftables systemctl start nftables nft list ruleset |
(注意) 必ずブロックリストに一時的にテスト接続のIPアドレスを追加し動作確認を行うこと!!
デバッグ
動作に問題がある場合は、ログを出力し確認します。
・ ログの設定(rsyslog)
1 2 3 4 |
# logging nftables log to the separate files. if $msg contains 'nftables-' then /var/log/nftables.log # discarding them not to appear in /var/log/message if $msg contains 'nftables-' then stop |
rsyslogを再起動します。
・ nftablesの設定例
ip saddr @block_list_ipv4 log prefix “nftables-drop: “ reject
(注意)prefixで指定する文字列をrsyslogで設定しログファイルに出力するので、同じ文字列を含むものを指定すること。