Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

【Cent OS 6.x】国単位でIPをブロックするスクリプト with ipset

More than 3 years have passed since last update.

【Cent OS 6.x】国単位でIPをブロックするスクリプト with ipset

QIITAの皆さんの投稿にいつもお世話になっているのでたまには自分も投稿してみます。
ググれば正直似たようなのはいくつでも見つかるのですが、自分的にこれが一番いいかな、と調整したやつです。
よかったらレビューおなしゃす!

簡単に言うと、特定の国のIPリストを取得してそれ以外はブロックするIPTABLEを書き込むスクリプト。
前につくったやつです。
CENTOS7はiptableじゃないのでたぶんダメです。

なお、国リストは
http://nami.jp/ipv4bycc/cidr.txt.gz
から取得しています。

準備、設置、構成など

ipsetが必要なので先にインストールしておきます。

sudo yum -y install ipset

/root/以下にipというディレクトリを作成し、ホワイトリスト、ブラックリストファイルを作成する。
こんな感じ。権限は適宜調整してね。
もちろん、別のディレクトリでもかまわないです。その場合はスクリプトの該当箇所DIRECTORYを修正して下さい。

#準備として下記が必要。
sudo mkdir ${DIRECTORY} && cd ${DIRECTORY} && sudo touch allow_ip && sudo touch deny_ip && sudo touch allow_country
sudo chmod +x allow_ip && sudo chmod +x deny_ip && sudo chmod +x allow_country
root
    ip
        allow_ip    =>  ホワイトリストするIP
        allow_country   =>  ホワイトリストする国。
        deny_ip     =>  ブラックリストするIP

allow_ipには無条件で接続を許可したいIPを1行に一つずつ書きます。
allow_country には無条件で接続を許可したい国を1行に一つずつ書きます。
deny_ip には無条件で接続を拒否したいIPを1行に一つずつ書きます。

deny_ipは『日本のIPだけど、こいつは悪いヤツなのでブロックしたい』みたいな場合ですね。
なお、deny_countryは許可していないければドロップされますので原則必要ありません。
例えば、逆のパターンで『特定の国のみブロックしたい場合』とかならdeny_countryだけ記述して
それに合わせてスクリプトを調整すればOKです。

使い方

下記スクリプトを ipset.shとして保存して ./ipset.sh 22 というように叩けばOK.
引数の22はSSHポート。分かりやすい例として22としたが、ここは間違えないように注意!

ipset.sh

#! /bin/bash
#################################################################################                       
#ISSUE DATE 2016/12/09                          
#VERSION    v1.0.0.0                            
#DESCRIPTION    IPTABLE MANAGEMENT                      
#REQUIRE    IPTABLE AND IPSET                       
#USAGE      ./ipset.sh 22                           
#PLEASE SET THE WHITEL LIST ON  BLACK LIST                  
#WHITEL LIST            ${DIRECTORY}allow_ip 
#WHITE LIST BY COUNTRY      ${DIRECTORY}allow_country           
#BLACK LIST             ${DIRECTORY}deny_ip
#################################################################################
#PLEASE CHANGE THESE SETTINGS BELOW
#################################################################################
## SSH_PORT
SSH_PORT=$1;
#################################################################################
## DIRECTORY 適宜修正。
DIRECTORY=/root/ip/
#################################################################################
#CHECK
if [ "${SSH_PORT}" = "" ]; then
   echo "NO SSH_PORT!"
   exit 0
fi

#################################################################################
if [ ! -d "$DIRECTORY" ]; then
    sudo mkdir ${DIRECTORY};
    sudo chmod +x ${DIRECTORY};
fi
#################################################################################
cd ${DIRECTORY}
#################################################################################
## CHECK OLD LOG FILE
if [ -s ${DIRECTORY}cidr.txt ]; then
    if [ -s ${DIRECTORY}cidr.txt.old ]; then
        sudo rm -rf ${DIRECTORY}cidr.txt.old;
    fi
    sudo mv ${DIRECTORY}cidr.txt ${DIRECTORY}cidr.txt.old;
fi
#################################################################################
## 国別コードリストをダウンロード
sudo wget -nv -O - http://nami.jp/ipv4bycc/cidr.txt.gz | sudo gunzip -c > ${DIRECTORY}cidr.txt;
IPDIFF=$(sudo diff ${DIRECTORY}cidr.txt.old ${DIRECTORY}cidr.txt | sudo grep -c "^<");
#################################################################################
if [ $IPDIFF -gt 200 ]; then
    # 正常に取得できなかったリストを削除
    sudo rm -rf ${DIRECTORY}cidr.txt;
else
    # ホワイトリストセットを作成
    sudo ipset create -exist WHITELIST hash:net;
    sudo ipset create -exist BLACKLIST hash:net;
    sudo ipset flush WHITELIST;
    sudo ipset flush BLACKLIST;

    # ホワイトリストセットにIPアドレスを登録
        ALLOW_COUNTRY_FILE=${DIRECTORY}allow_country;
        while read allow_country; do
        echo $allow_country;
            sudo sed -n "s/^\(${allow_country}\)\t//p" ${DIRECTORY}cidr.txt | while read ALLOW_ADDRESS; do
            echo $ALLOW_ADDRESS;
                sudo ipset add WHITELIST $ALLOW_ADDRESS;
            done
        done < $ALLOW_COUNTRY_FILE

    ALLOW_FILE=${DIRECTORY}allow_ip;
    while read allow_ip; do
        echo $allow_ip;
        sudo ipset add WHITELIST $allow_ip;
    done < $ALLOW_FILE

    #下記は原則不要だが、特定の国以外は全て許可!のようなケースではこっちを使うべきか。
    #sed -n 's/^\(CN\|US\|CA\|EG\|IN\|ID\|VI\|VG\|VN\|KP\|KR\|DE\|RU\|NL\|PK\|FR\|BR\|MO\|TH\|SG\|PH\|VD\|IR\|CY\|GB\|DD\|RO\|MY\|MN\|TP\|IT\|SE\|CH\)\t//p' ${DIRECTORY}cidr.txt | while read DENY_ADDRESS; do
    #    sudo ipset add BLACKLIST $DENY_ADDRESS
    #done

    DENY_FILE=${DIRECTORY}deny_ip;
    while read deny_ip; do
        sudo ipset add BLACKLIST $deny_ip;
    done < $DENY_FILE

    #echo "set /etc/nginx/conf.d/dropip.conf";
    #sudo rm -rf /etc/nginx/conf.d/dropip.conf;

    sudo ipset save;
    #sudo ipset save | tee restore_command
    #sudo ipset restore < restore_command
    echo "save ipset";

    sudo service iptables stop;

    # iptables 初期化
    sudo iptables -F INPUT;
    sudo iptables -F OUTPUT;
    sudo iptables -F FORWARD;

    # 受信/ 送信 / 通過
    sudo iptables -P INPUT DROP;
    sudo iptables -P OUTPUT ACCEPT;
    sudo iptables -P FORWARD DROP;

    sudo iptables -A INPUT -p tcp ! --tcp-flags SYN,RST,ACK SYN -m state --state NEW -j DROP;
    sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT;

    ## ポート開放 ##
    sudo iptables -A INPUT -i lo -j ACCEPT;
    sudo iptables -A OUTPUT -o lo -j ACCEPT;

    # IP Spoofing
    sudo iptables -A INPUT -i eth0 -s 127.0.0.1/8 -j DROP;
    sudo iptables -A INPUT -i eth0 -s 10.0.0.0/8 -j DROP;
    sudo iptables -A INPUT -i eth0 -s 172.16.0.0/12 -j DROP;
    sudo iptables -A INPUT -i eth0 -s 192.168.0.0/16 -j DROP;
    sudo iptables -A INPUT -i eth0 -s 192.168.0.0/24  -j DROP;

    # Ping、Ping Flood
    sudo iptables -N PING_ATTACK;
    sudo iptables -A PING_ATTACK -m length --length :85 -m limit --limit 1/s --limit-burst 4 -j ACCEPT;
    sudo iptables -A PING_ATTACK -j LOG --log-prefix "[IPTABLES PINGATTACK] : " --log-level=debug;
    sudo iptables -A PING_ATTACK -j DROP;
    sudo iptables -A INPUT -p icmp --icmp-type 8 -j PING_ATTACK;

    # Smurf
    sudo iptables -A INPUT -d 255.255.255.255 -j DROP;
    sudo iptables -A INPUT -d 224.0.0.1 -j DROP;
    sudo iptables -A INPUT -d 192.168.0.255 -j DROP;

    # Auth/IDENT
    sudo iptables -A INPUT -p tcp --dport 113 -i eth0 -j REJECT --reject-with tcp-reset;

    # DNS
    sudo iptables -N DNSAMP;
    sudo iptables -A DNSAMP -m recent --name dnsamp --set;
    sudo iptables -A DNSAMP -m recent --name dnsamp --rcheck --seconds 60 --hitcount 5 -j LOG --log-prefix "[IPTABLES DNSAMP] : " --log-level=debug;
    sudo iptables -A DNSAMP -m recent --name dnsamp --rcheck --seconds 60 --hitcount 5 -j DROP;
    sudo iptables -A DNSAMP -j ACCEPT;

    sudo iptables -A INPUT -p udp -m state --state NEW --dport 53 -i eth0 -j DNSAMP;
    sudo iptables -A INPUT -p tcp -m state --state NEW --dport 53 -j ACCEPT;

    # smtps
    sudo iptables -A INPUT -p tcp -m state --state NEW --dport 465 -j ACCEPT;

    # imaps
    sudo iptables -A INPUT -p tcp -m state --state NEW --dport 993 -j ACCEPT;

    # pop3s
    sudo iptables -A INPUT -p tcp -m state --state NEW --dport 995 -j ACCEPT;

    # smtp tcp
    sudo iptables -A INPUT -p tcp -m state --state NEW --dport 25 -j ACCEPT;

    # サブミッションポート
    sudo iptables -A INPUT -p tcp -m state --state NEW --dport 587 -j ACCEPT;

    # SSH PORT
    sudo iptables -I INPUT -m state --state NEW -p tcp --dport $SSH_PORT -m set --match-set WHITELIST src -j ACCEPT;

    # 公開PORT(適宜修正してね)
    #sudo iptables -I INPUT -m state --state NEW -p tcp --dport 10022 -m set --match-set WHITELIST src -j ACCEPT;
    #sudo iptables -I INPUT -m state --state NEW -p tcp --dport 6379 -m set --match-set WHITELIST src -j ACCEPT;
    sudo iptables -I INPUT -m state --state NEW -p tcp --dport 80 -m set --match-set WHITELIST src -j ACCEPT;
    #sudo iptables -I INPUT -m state --state NEW -p tcp --dport 8000 -m set --match-set WHITELIST src -j ACCEPT;
    #sudo iptables -I INPUT -m state --state NEW -p tcp --dport 3306 -m set --match-set WHITELIST src -j ACCEPT;
    sudo iptables -I INPUT -m state --state NEW -p tcp --dport 443 -m set --match-set WHITELIST src -j ACCEPT;

    sudo iptables -A INPUT -m limit --limit 1/s -j LOG --log-prefix "[IPTABLES DROP INPUT] : " --log-level=debug;
    sudo iptables -A INPUT -j DROP;

    sudo service iptables start;
    sudo service iptables save;

    #MSG
    echo "complete";

    # Smurf
    sudo sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1 > /dev/null;
    sudo sed -i '/# Disable Broadcast Ping/d' /etc/sysctl.conf;
    sudo sed -i '/net.ipv4.icmp_echo_ignore_broadcasts/d' /etc/sysctl.conf;
    sudo echo "# Disable Broadcast Ping" >> /etc/sysctl.conf;
    sudo echo "net.ipv4.icmp_echo_ignore_broadcasts=1" >> /etc/sysctl.conf;


    # SYN flood
    sudo sysctl -w net.ipv4.tcp_syncookies=1 > /dev/null;
    sudo sed -i '/# Enable SYN Cookie/d' /etc/sysctl.conf;
    sudo sed -i '/net.ipv4.tcp_syncookies/d' /etc/sysctl.conf;

    sudo echo "# Enable SYN Cookie" >> /etc/sysctl.conf;
    sudo echo "net.ipv4.tcp_syncookies=1" >> /etc/sysctl.conf;

    sudo sysctl -p;
fi
#################################################################################
exit 0;
#################################################################################

これでOK。
あとは、CRONにでも登録しておけば、定期的にIPリストを更新し、IPTABLEにセットしてくれます。

適当に怪しいやつも弾いてくれます。
あ、IPv6は対応してないのであしからず!

運用していて特に問題はありませんが、あくまでも自己責任で!

※利用は自由ですが、責任などは一切持ちませんのであしからず。

ryoheiizm
過去にはWINDOWSアプリ作っていましたが、もっぱらWEB系の人間です。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away