ipsetとiptablesでSSHを日本国内からの接続に限定する (CentOS 7)
はじめに
ひとつ前の記事で、国別のIPアドレスリストを利用して、ipsetとiptablesでSSHを日本国内からの接続に限定する設定方法をまとめました。
・ipsetとiptablesでSSHを日本国内からの接続に限定する (CentOS 6)
https://inaba-serverdesign.jp/blog/20150209/ipset_iptables_country_centos6.html
続いてCentOS 7でもこの方法で、と試してみたのですが、CentOS 7のipsetは(2015年2月時点では)systemdに対応しておらず、OS起動時にipsetセットがロードされません。
このためCentOS 7での設定はあきらめていたのですが、Fedora Projectのipset RPMパッケージがsystemdに対応していることがわかり、試しにCentOS 7で適用してみると問題なく動作しているので、ここでまとめておきます。
(2020.4.22追記ここから)
↑このように書きましたが、最近確認したところ、CentOS 7のipsetも、ipset-serviceパッケージでsystemdに対応していました。
この記事を書いた当時もipset-serviceパッケージが存在していたとしたら、私の知識・調査不足でした。
以下、少し修正しました。
(2020.4.22追記ここまで)
※自己責任でお試しください。
ipsetの設定
Fedora 21のipset RPMパッケージをダウンロードします。
‘ipset-service’ がipsetのsystemd向けのサービス管理パッケージです。
※Fedora 20, Fedora 22のipsetもsystemdに対応しているので、そのRPMパッケージでもよいと思います。
# cd /usr/local/src/
# wget http://ftp.riken.jp/Linux/fedora/releases/21/Everything/x86_64/os/Packages/i/ipset-6.21.1-4.fc21.x86_64.rpm
# wget http://ftp.riken.jp/Linux/fedora/releases/21/Everything/x86_64/os/Packages/i/ipset-libs-6.21.1-4.fc21.x86_64.rpm
# wget http://ftp.riken.jp/Linux/fedora/releases/21/Everything/x86_64/os/Packages/i/ipset-service-6.21.1-4.fc21.noarch.rpm
インストールします。
# rpm -ivh ipset-6.21.1-4.fc21.x86_64.rpm \
ipset-libs-6.21.1-4.fc21.x86_64.rpm \
ipset-service-6.21.1-4.fc21.noarch.rpm
(2020.4.22追記ここから)
ipsetに必要なパッケージをインストールします。
‘ipset-service’ がipsetのsystemd向けのサービス管理パッケージです。
# yum install ipset ipset-libs ipset-service
(2020.4.22追記ここまで)
・ホワイトリストセットの作成
接続を許可したいネットワークのアドレスを保持するセット「WHITELIST」を作成し、国別コードリストからWHITELISTのエントリーを登録します。
定期的に最新の国別コードリストの情報を反映できるよう、スクリプトを用意しました。
# vi mk_ipwhitelist.sh #!/bin/bash # 国別コードリストをダウンロード cd /root/bin/ if [ -s cidr.txt ]; then mv cidr.txt cidr.txt.old fi wget http://nami.jp/ipv4bycc/cidr.txt.gz gunzip cidr.txt.gz # ホワイトリストセットを作成 ipset create -exist WHITELIST hash:net # ホワイトリストセットに日本のIPアドレスを登録 sed -n 's/^JP\t//p' cidr.txt | while read ADDRESS; do ipset add WHITELIST $ADDRESS done
スクリプトを実行します。
# chmod 700 ./mk_ipwhitelist.sh # ./mk_ipwhitelist.sh
WHITELISTを確認します。
# ipset list WHITELIST | less Name: WHITELIST Type: hash:net Header: family inet hashsize 1024 maxelem 65536 Size in memory: 48176 References: 0 Members: 112.138.0.0/15 138.212.0.0/16 192.42.104.0/22 202.177.48.0/20 ...
・ipsetセットの保存
ipsetはサービスを再起動すると削除されるため、/etc/sysconfig/ipset に保存し、次回ipsetが起動するときに自動的にWHITELISTセットをロードするようにします。
※起動停止スクリプト /usr/libexec/ipset/ipset.start-stop において、ipsetのデータファイルは /etc/sysconfig/ipset ではなく /etc/ipset/ipset と定義されていることに注意してください。
(2020.4.22追記ここから)
↑これは、Fedoraのipset-serviceをインストールした場合。CentOS 7のipset-serviceをインストールした場合は、ipsetのデータファイルは、/etc/sysconfig/ipsetです。
(2020.4.22追記ここまで)
# view /usr/libexec/ipset/ipset.start-stop IPSET_BIN=/usr/sbin/ipset IPSET_CONFIG=/etc/sysconfig/ipset-config IPSET_DATA_COMPAT=/etc/sysconfig/ipset ...
ipsetセットを保存し、内容を確認します。
# ipset save > /etc/sysconfig/ipset # less /etc/sysconfig/ipset create WHITELIST hash:net family inet hashsize 1024 maxelem 65536 add WHITELIST 103.8.88.0/21 add WHITELIST 120.72.64.0/20 add WHITELIST 59.190.0.0/16 ...
・ipsetの起動
ステータスを確認します。
# systemctl status ipset ipset.service - IP sets for iptables Loaded: loaded (/usr/lib/systemd/system/ipset.service; disabled) Active: inactive (dead)
起動します。
# systemctl start ipset # systemctl status ipset ipset.service - IP sets for iptables Loaded: loaded (/usr/lib/systemd/system/ipset.service; disabled) Active: active (exited) since 土 2015-02-07 15:42:44 JST; 3s ago Process: 28826 ExecStart=/usr/libexec/ipset/ipset.start-stop start (code=exited, status=0/SUCCESS) Main PID: 28826 (code=exited, status=0/SUCCESS) 2月 07 15:42:44 hostname systemd[1]: Starting IP sets for iptables... 2月 07 15:42:44 hostname ipset.start-stop[28826]: Loaded with no configuration 2月 07 15:42:44 hostname systemd[1]: Started IP sets for iptables. Hint: Some lines were ellipsized, use -l to show in full.
・自動起動設定
OS起動時にipsetセットをロードするよう自動起動設定を行います。
# systemctl enable ipset ln -s '/usr/lib/systemd/system/ipset.service' '/etc/systemd/system/basic.target.wants/ipset.service' # systemctl status ipset ipset.service - IP sets for iptables Loaded: loaded (/usr/lib/systemd/system/ipset.service; enabled) Active: active (exited) since 土 2015-02-07 15:42:44 JST; 57s ago Main PID: 28826 (code=exited, status=0/SUCCESS) 2月 07 15:42:44 hostname systemd[1]: Starting IP sets for iptables... 2月 07 15:42:44 hostname ipset.start-stop[28826]: Loaded with no configuration 2月 07 15:42:44 hostname systemd[1]: Started IP sets for iptables. Hint: Some lines were ellipsized, use -l to show in full.
iptablesの設定
iptablesコマンドでオプション -m set –match-set <セット名=WHITELIST> src を指定して、ホワイトリストのIPアドレスからのみSSH接続を許可します。
(デフォルトポリシーがDROP、SSHポートはTCP/22を想定。)
# iptables -I INPUT -m state --state NEW -p tcp --dport 22 -m set --match-set WHITELIST src -j ACCEPT
これで、iptables 1行のエントリーで、大量のIPアドレスからのアクセス許可ルールを表現できました。
iptablesコマンドでは source 0.0.0.0/0 と出力されますが、ホワイトリストにマッチしないIPアドレスからはSSHポートにアクセスできません。
# iptables -L -n Chain INPUT (policy DROP) target prot opt source destination ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22 match-set WHITELIST src
ルールを追加したので、iptablesルールを保存するのをお忘れなく。
# iptables-save > /etc/sysconfig/iptables # less /etc/sysconfig/iptables *filter :INPUT DROP [0:0] :FORWARD DROP [0:0] :OUTPUT DROP [16000:1808000] -A INPUT -p tcp -m state --state NEW -m tcp --dport 10022 -m set --match-set WHITELIST src -j ACCEPT ...
動作確認
以下を確認します。
- 自分のPCやサーバーからSSHログインできる。
- 海外のサーバー環境からSSHログインできない。
また、可能であれば、OSを再起動してipsetルールやiptablesルールが正しくロードされることも確認するとよいでしょう。
「海外のサーバー環境」は、例えばAWS EC2のサーバーを使うとよいと思います。
なお、EC2サーバーのIPアドレスは、東京リージョンのサーバーでも国名コードとしては’US’です。
つまり、この国名コードは、必ずしも該当のIPアドレスを使用するサーバーの地理的な位置を表すとは限らないことに注意しましょう。
まとめ
CentOS 7で、国別のIPアドレスリストを利用して、ipsetとiptablesでSSHを日本国内からの接続に限定する設定方法をまとめました。
この方法で、FTP等ほかのポートのアクセス制限を行うこともできますし、ipsetでブラックリストのセットを作成しDROPルールを登録することで、特定の国からのアクセスを防ぐこともできます。
# iptables -I INPUT -m state --state NEW -p tcp --dport 22 -m set --match-set BLACKLIST src -j DROP
iptablesで取り扱うIPアドレスが多い場合は、ipsetを使いましょう。
(関連記事)
・nftablesでSSHを日本国内からの接続に限定する (CentOS 8)
https://inaba-serverdesign.jp/blog/20191219/nftables-country-ipaddress-centos8.html
・ipsetとiptablesでSSHを日本国内からの接続に限定する (CentOS 6)
https://inaba-serverdesign.jp/blog/20150209/ipset_iptables_country_centos6.html
・Nginxで海外からのアクセスを拒否する
https://inaba-serverdesign.jp/blog/20140616/nginx_deny_ipaddress.html