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

#【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は対応してないのであしからず！


##運用していて特に問題はありませんが、あくまでも自己責任で！
※利用は自由ですが、責任などは一切持ちませんのであしからず。