●概要
※CentOS 8からTCP Wrapperは使用できなくなりました。
参考URL:hosts.allow で sshd への接続を日本国内のみに制限する
海外から自宅サーバのSSHへの不正アクセスが多く、ルータで一つ一つ拒否設定を設定していく作業が煩わしい。
このため、自宅サーバのSSHへのアクセスは原則国内限定とし、更に国内から不正アクセス検知時のみルータで拒否設定する方針に変更したいと思いました。
国内限定するにしても、そのネットワークアドレスは非常に多く、/etc/hosts.allow、/etc/hosts.denyを利用することとします。
これまで利用してきた、firewalld、denyhosts、fail2ban等はそのまま利用します。
●設定(Rocky 8、Rocky 9)
参考URL:システムエクスプレス株式会社
参考URL:ipsetで大量のBlock指定を行う
国内のIPアドレスのリストを作成します。
ipsetの再適用
現在適用されたipsetを削除するには下記のようにします。
ただし、削除するエントリーのファイル名が同じでも追加した時の内容と異なっている場合、削除しても下記のようにエントリーが残ってしまうことがあります。
Rocky 9における、インターネット側からhttp及びhttpsでアクセスできない現象への対応
CentOS Stream 8、Rocky 8では起きていなかった現象がRocky 9で発生しました。
tcpdumpで調べると(157.65.27.0/24は、今回ポート開放確認のために使用したサイト)
そこで、nftコマンドでフィルタールールを調べてみます。
いろいろ調べた結果(firewalldを停止すると接続できるようになる)、domesticゾーンによる影響でした。
イントラネットからでもアクセスできるようにpublicゾーンに設定済みの、http及びhttpsはそのまま残しておきます。
(残しておかないと、イントラでの接続が出来なくなります。)
●設定(CentOS 7)
複数のCIDRブロックを集約 (aggregation) するため、aggregateをyumでインストールします。
ローカルホストからのアクセスは許可するために、hosts.allowの先頭に次の1行を追加します。
※CentOS 8からTCP Wrapperは使用できなくなりました。
参考URL:hosts.allow で sshd への接続を日本国内のみに制限する
海外から自宅サーバのSSHへの不正アクセスが多く、ルータで一つ一つ拒否設定を設定していく作業が煩わしい。
このため、自宅サーバのSSHへのアクセスは原則国内限定とし、更に国内から不正アクセス検知時のみルータで拒否設定する方針に変更したいと思いました。
国内限定するにしても、そのネットワークアドレスは非常に多く、/etc/hosts.allow、/etc/hosts.denyを利用することとします。
これまで利用してきた、firewalld、denyhosts、fail2ban等はそのまま利用します。
●設定(Rocky 8、Rocky 9)
参考URL:システムエクスプレス株式会社
参考URL:ipsetで大量のBlock指定を行う
国内のIPアドレスのリストを作成します。
# mkdir /root/iptables # vi /root/iptables/jpip_setup.sh #!/bin/bash COUNTRYLIST='JP' curl -s -o /root/iptables/delegated-apnic-latest http://ftp.apnic.net/stats/apnic/delegated-apnic-latest :> /root/iptables/jpip for country in $COUNTRYLIST do for ip in `cat /root/iptables/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" >> /root/iptables/jpip done done # chmod 700 /root/iptables/jpip_setup.sh # /root/iptables/jpip_setup.shfirewallを設定します。
# domestic(国内)というゾーンを作成します。 firewall-cmd --permanent --new-zone=domestic # domestic という ipset を作成して type を hash:net にします。 firewall-cmd --permanent --new-ipset=domestic --type=hash:net # 上記で作った国内のIPリストファイルをこの ipset に読み込みます。 firewall-cmd --permanent --ipset=domestic --add-entries-from-file=/root/iptables/jpip # この ipset に国内IPリストが読み込まれているか確認します。 firewall-cmd --permanent --info-ipset=domestic # 読み込まれた ipset をこのゾーンに適用します。 firewall-cmd --permanent --zone=domestic --add-source=ipset:domestic # publicゾーンからSSHサービスを削除します。 # firewall-cmd --permanent --zone=public --remove-service=ssh # domesticゾーンにSSHサービスを追加します。 # firewall-cmd --permanent --zone=domestic --add-service=ssh firewalld を reload します。 # firewall-cmd --reload以上でsshdへの接続は日本国内のみに制限されました。
ipsetの再適用
現在適用されたipsetを削除するには下記のようにします。
# firewall-cmd --permanent --ipset=domestic --remove-entries-from-file=/root/iptables/jpip
# firewall-cmd --reload
# ipset --list domestic
Name: domestic
Type: hash:net
Revision: 6
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 376
References: 0
Number of entries: 0
Members:
エントリー数が「0」であれば、(問題なく)全て削除されています。
ただし、削除するエントリーのファイル名が同じでも追加した時の内容と異なっている場合、削除しても下記のようにエントリーが残ってしまうことがあります。
# firewall-cmd --permanent --ipset=domestic --add-entries-from-file=/root/iptables/jpip_local_ip ← 故意に、ローカルネットワークが余計に追加されているセットを適用 # firewall-cmd --reload プライベートアドレスが記載されていないエントリーファイルでipsetを削除 # firewall-cmd --permanent --ipset=domestic --remove-entries-from-file=/root/iptables/jpip # firewall-cmd --reload # ipset --list domestic Name: domestic Type: hash:net Revision: 6 Header: family inet hashsize 1024 maxelem 65536 Size in memory: 568 References: 0 Number of entries: 3 Members: 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16このように新たなエントリーファイルを再適用するには注意して対応する必要があります。
Rocky 9における、インターネット側からhttp及びhttpsでアクセスできない現象への対応
CentOS Stream 8、Rocky 8では起きていなかった現象がRocky 9で発生しました。
tcpdumpで調べると(157.65.27.0/24は、今回ポート開放確認のために使用したサイト)
# tcpdump -i eno1 net 157.65.27.0 mask 255.255.255.0
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eno1, link-type EN10MB (Ethernet), snapshot length 262144 bytes
17:39:02.885522 IP 157-65-27-7.vpscloud.static.arena.ne.jp.49354 > hostA.http: Flags [S], seq 894457425, win 29200, options [mss 1420,sackOK,TS val 232270987 ecr 0,nop,wscale 7], length 0
17:39:02.885625 IP hostA > 157-65-27-7.vpscloud.static.arena.ne.jp: ICMP host hostA unreachable - admin prohibited filter, length 68
のようになり、デフォルトでフィルターがかかっているっぽい。
そこで、nftコマンドでフィルタールールを調べてみます。
・CentOS Stream 8 # nft list ruleset | grep -n reject 214: reject with icmpx admin-prohibited 222: ip6 daddr { ::/96, ::ffff:0.0.0.0/96, 2002::/24, 2002:a00::/24, 2002:7f00::/24, 2002:a9fe::/32, 2002:ac10::/28, 2002:c0a8::/32, 2002:e000::/19 } reject with icmpv6 addr-unreachable 230: reject with icmpx admin-prohibited 237: ip6 daddr { ::/96, ::ffff:0.0.0.0/96, 2002::/24, 2002:a00::/24, 2002:7f00::/24, 2002:a9fe::/32, 2002:ac10::/28, 2002:c0a8::/32, 2002:e000::/19 } reject with icmpv6 addr-unreachable ・Rocky Linux 9 # nft list ruleset | grep -n reject 2350: reject with icmpx admin-prohibited 2359: ip6 daddr { ::/96, ::ffff:0.0.0.0/96, 2002::/24, 2002:a00::/24, 2002:7f00::/24, 2002:a9fe::/32, 2002:ac10::/28, 2002:c0a8::/32, 2002:e000::/19 } reject with icmpv6 addr-unreachable 2361: reject with icmpx admin-prohibited 2368: ip6 daddr { ::/96, ::ffff:0.0.0.0/96, 2002::/24, 2002:a00::/24, 2002:7f00::/24, 2002:a9fe::/32, 2002:ac10::/28, 2002:c0a8::/32, 2002:e000::/19 } reject with icmpv6 addr-unreachable 2415: reject with icmpx admin-prohibited 2467: reject with icmpx admin-prohibited 2544: reject with icmpx admin-prohibited 2626: reject with icmpx admin-prohibited明らかに違いがあります。
いろいろ調べた結果(firewalldを停止すると接続できるようになる)、domesticゾーンによる影響でした。
イントラネットからでもアクセスできるようにpublicゾーンに設定済みの、http及びhttpsはそのまま残しておきます。
(残しておかないと、イントラでの接続が出来なくなります。)
# firewall-cmd --permanent --zone=domestic --add-service={http,https} # firewall-cmd --reload # firewall-cmd --list-all --zone=domestic : services: http https ssh :このように対応することで、インターネット側から接続できるようになりました。
●設定(CentOS 7)
複数のCIDRブロックを集約 (aggregation) するため、aggregateをyumでインストールします。
# yum install -y aggregate各ファイルを格納するためのディレクトリを作成します。
# mkdir /root/countryfilter # cd /root/countryfilter
# vi conv.pl #!/bin/perl use strict; while (<STDIN>) { chomp; my ($registry, $cc, $type, $start, $value, undef, $status) = split(/\|/); unless ($type eq 'ipv4' && ($status eq 'allocated' || $status eq 'assigned')) { next; } #unless ($cc eq 'JP') { next; } my $SubnetMaskBin = sprintf('%b', scalar($value)); if ($SubnetMaskBin !~ /^1(0+)$/) { # CIDR 表記できない next; } my $prefix = 32 - length($1); my $num; $num = ($num << 8) + $_ foreach (split(/\./, $start)); if (($num % $value) != 0) { # 分割しなければならない next; } print $start.'/'.$prefix."\t".$cc."\n"; } while (<STDIN>) { chomp; my ($registry, $cc, $type, $start, $value, undef, $status) = split(/\|/); unless ($type eq 'ipv4' && ($status eq 'allocated' || $status eq 'assigned')) { next; } #unless ($cc eq 'JP') { next; } my $SubnetMaskBin = sprintf('%b', scalar($value)); if ($SubnetMaskBin !~ /^1(0+)$/) { # CIDR 表記できない next; } my $prefix = 32 - length($1); my $num; $num = ($num << 8) + $_ foreach (split(/\./, $start)); if (($num % $value) != 0) { # 分割しなければならない next; } print $start.'/'.$prefix."\t".$cc."\n"; }日本国内のIPアドレスリスト(ip.txt)を生成してhosts.allowに書き込むシェルスクリプト(update.sh)を作成します。
# vi update.sh R=$(cd $(dirname $0); pwd) cd $DIR # aggregate がインストールされているかチェック aggregate=`which aggregate 2> /dev/null | wc -l` if [ $aggregate -ne 1 ]; then echo "aggregate: command not found" >&2 exit 1 fi # 各 RIP から IP アドレスの割当リストを取得 rm -f ./delegated-* wget ftp://ftp.arin.net/pub/stats/arin/delegated-arin-latest > /dev/null 2>&1 wget ftp://ftp.ripe.net/pub/stats/ripencc/delegated-ripencc-latest > /dev/null 2>&1 wget ftp://ftp.apnic.net/pub/stats/apnic/delegated-apnic-latest > /dev/null 2>&1 wget ftp://ftp.lacnic.net/pub/stats/lacnic/delegated-lacnic-latest > /dev/null 2>&1 wget ftp://ftp.afrinic.net/pub/stats/afrinic/delegated-afrinic-latest > /dev/null 2>&1 if [ ! -f delegated-apnic-latest ]; then echo "delegated-apnic-latest was not found." >&2 exit 1 fi # 日本国内のもののみを取り出して集約 cat delegated-* | perl ./countryfilter/conv.pl | grep -E 'JP$' | sort -n | aggregate -q > jp.txt # CIDR 表記をサブネットマスク表記に変換 sed -i 's/\/8$/\/255.0.0.0 /' ./jp.txt sed -i 's/\/9$/\/255.128.0.0 /' ./jp.txt sed -i 's/\/10$/\/255.192.0.0 /' ./jp.txt sed -i 's/\/11$/\/255.224.0.0 /' ./jp.txt sed -i 's/\/12$/\/255.240.0.0 /' ./jp.txt sed -i 's/\/13$/\/255.248.0.0 /' ./jp.txt sed -i 's/\/14$/\/255.252.0.0 /' ./jp.txt sed -i 's/\/15$/\/255.254.0.0 /' ./jp.txt sed -i 's/\/16$/\/255.255.0.0 /' ./jp.txt sed -i 's/\/17$/\/255.255.128.0 /' ./jp.txt sed -i 's/\/18$/\/255.255.192.0 /' ./jp.txt sed -i 's/\/19$/\/255.255.224.0 /' ./jp.txt sed -i 's/\/20$/\/255.255.240.0 /' ./jp.txt sed -i 's/\/21$/\/255.255.248.0 /' ./jp.txt sed -i 's/\/22$/\/255.255.252.0 /' ./jp.txt sed -i 's/\/23$/\/255.255.254.0 /' ./jp.txt sed -i 's/\/24$/\/255.255.255.0 /' ./jp.txt sed -i 's/\/25$/\/255.255.255.128 /' ./jp.txt sed -i 's/\/26$/\/255.255.255.192 /' ./jp.txt sed -i 's/\/27$/\/255.255.255.224 /' ./jp.txt sed -i 's/\/28$/\/255.255.255.240 /' ./jp.txt # /etc/hosts.allow をバックアップ NOW_TIME=`date +%Y%m%d_%H%M%S` cp -p /etc/hosts.allow /etc/hosts.allow_bk${NOW_TIME} # /etc/hosts.allow をリセット sed -i -e '/#countryfilter/d' /etc/hosts.allow # 日本国内の IP アドレスリストを書込 cat ./jp.txt | awk '{print "sshd: "$1" #countryfilter"}' >> /etc/hosts.allowhosts.denyを編集して、sshdへのアクセスを原則禁止とします。
# vi /etc/hosts.deny sshd: ALL※ sshで作業している場合、この時点で切断すると再接続できなくなるので注意してください。
ローカルホストからのアクセスは許可するために、hosts.allowの先頭に次の1行を追加します。
# vi /etc/hosts.allow ALL: 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, (その他のNWアドレス等) :作成したシェルスクリプトに実行権を与えて、実行します。
# chmod 700 update.sh # ./update.shcronで一週間ごとに実行するように設定します。
# ln -s /root/countryfilter/update.sh /etc/cron.weekly/以上でsshdへの接続は日本国内のみに制限されました。