BLOGTIMES
2017/01/28

firewalld + ipset で IP ブラックリスト(+ホワイトリストも)設定

  centos7  firewalld  tutorial 
このエントリーをはてなブックマークに追加

サーバに IP 制限をかけたいと思ったのですが、CentOS 7.x からはアクセス制御が iptables ではなく firewalld に変更されています。 iptables は依然として firewalld の下で動いているので、やろうと思えば iptables で IP 制限をすることもできますが、制限する IP のリストが大きくなった場合、iptables はあまり効率が良くないのと、管理も煩雑化してしまうため、今回は ipset を用いて IP 制限を行うことにしました。

IP sets

IP sets are a framework inside the Linux kernel, which can be administered by the ipset utility. Depending on the type, an IP set may store IP addresses, networks, (TCP/UDP) port numbers, MAC addresses, interface names or combinations of them in a way, which ensures lightning speed when matching an entry against a set.

インストールは yum で

インストールは yum で一撃です。
もしfail2ban をインストールしている場合には、既にインストールされているはずです。

yum install -y ipset

まずは設定ファイルを作る

設定方法は「firewalld + ipset でアクセス制限 | server-memo.net」を参考にさせていただきました。
今回はアクセス制限用のリストを作るので BLACKLIST という名前にしています。

まずは設定を保存するための /etc/ipset というディレクトリを作成して、ユーティリティ用のスクリプトを作ります。

# 設定用のディレクトリを作成 mkdir -p /etc/ipset # ユーティリティ (add.sh restore.sh save.sh) を生成 cd /etc/ipset cat << 'EOS' >add.sh #!/bin/bash SCRIPT_DIR=`dirname $0` cd $SCRIPT_DIR IPSET=/sbin/ipset CONF=BLACKLIST TS="`date --iso-8601=seconds`" if [ -n "$1" ] ; then $IPSET add $CONF $1 else echo "Usage: $0 n.n.n.n/n" fi EOS cat << 'EOS' > restore.sh #!/bin/bash SCRIPT_DIR=`dirname $0` cd $SCRIPT_DIR IPSET=/sbin/ipset CONF=BLACKLIST CONF2=WHITELIST $IPSET destroy $CONF >/dev/null 2>&1 $IPSET restore < $CONF $IPSET destroy $CONF2 >/dev/null 2>&1 $IPSET restore < $CONF2 EOS cat << 'EOS' >save.sh #!/bin/bash SCRIPT_DIR=`dirname $0` cd $SCRIPT_DIR IPSET=/sbin/ipset CONF=BLACKLIST CONF2=WHITELIST $IPSET save $CONF > $CONF $IPSET save $CONF2 > $CONF2 EOS chmod 755 *.sh

次に ipset を使ってセットを作成し、作成したセットに IP アドレスを追加します。

# セット作成 ipset create BLACKLIST hash:net counters timeout 0 ipset create WHITELIST hash:net counters timeout 0 # 許可アドレスの追加(以下のコマンドを必要なだけ) ipset add WHITELIST 10.0.0.0/8 # 制限アドレスの追加(以下のコマンドを必要なだけ) ./add.sh 192.168.100.0/24 ./add.sh 192.168.101.1/32 # 保存のテスト(WHITELIST, BLACKLISTというファイルができるかどうか確認します) ./save.sh

最後に firewalld と連携したら完了です。

firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -m set ! --match-set WHITELIST src -m set --match-set BLACKLIST src -j DROP firewall-cmd --reload

※上記だと全ての通信を DROP してしまうので、特定のポートの通信のみを縛るには multiport を使って以下のように書くことができます。

firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -m multiport -p tcp --dports 22,80,443 -m set ! --match-set WHITELIST src -m set --match-set BLACKLIST src -j DROP firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -m multiport -p udp --dports 22,80,443 -m set ! --match-set WHITELIST src -m set --match-set BLACKLIST src -j DROP firewall-cmd --reload

ipset の内容は再起動したりすると消えてしまうので、以下のように firewalld のサービスの定義を変更して起動時と終了時に設定のリストアや保存を自動的に行うようにしておきます。

cp -a /usr/lib/systemd/system/firewalld.service /etc/systemd/system cd /etc/systemd/system patch <<'EOF' --- firewalld.service.org 2017-01-18 08:28:33.000000000 +0900 +++ firewalld.service 2017-01-28 21:45:36.985884227 +0900 @@ -10,6 +10,8 @@ [Service] EnvironmentFile=-/etc/sysconfig/firewalld +ExecStartPre=/etc/ipset/restore.sh +ExecStopPost=/etc/ipset/save.sh ExecStart=/usr/sbin/firewalld --nofork --nopid $FIREWALLD_ARGS ExecReload=/bin/kill -HUP $MAINPID # supress to log debug and error output also to /var/log/messages EOF systemctl daemon-reload

定義の内容や稼働状況は以下のコマンドで確認できます。

ipset list BLACKLIST

意外とシンプルに実現できました。

2017/2/4 追記

不便なのでホワイトリスト(無条件に許可するIP)も設定できるようにしました。

2022/9/21 追記

ipset が firewalld で管理されるようにしました。


    トラックバックについて
    Trackback URL:
    お気軽にどうぞ。トラックバック前にポリシーをお読みください。[policy]
    このエントリへのTrackbackにはこのURLが必要です→https://blog.cles.jp/item/9108
    Trackbacks
    このエントリにトラックバックはありません
    Comments
    愛のあるツッコミをお気軽にどうぞ。[policy]
    古いエントリについてはコメント制御しているため、即時に反映されないことがあります。
    コメントはありません
    Comments Form

    コメントは承認後の表示となります。
    OpenIDでログインすると、即時に公開されます。

    OpenID を使ってログインすることができます。

    Identity URL: Yahoo! JAPAN IDでログイン