事情的起因是不停的有国外ip扫描我阿里云服务器,于是想限制只能国内ip访问,期间用了
fail2ban
但是这个是被动防御,查阅相关资料后写了个脚本使用iptables
和ipset
来实现限制地区访问,区域列表来自 ipdeny
安装 ipset
sudo apt-get -y install ipset
iptables 常用命令
iptables -F # 清除预设链中规则
iptables -X # 清除自定义链中规则
iptables -A INPUT -i lo -j ACCEPT # 允许来自本机的全部连接
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT # 允许已建立的连接不中断
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT # 允许icmp协议,即允许ping服务器
iptables -A INPUT -m set ! --match-set china src -j DROP # 匹配china链,非国内IP则直接丢弃包
iptables -A INPUT -p udp --dport 5060 -j ACCEPT # 允许UDP协议的5060端口
iptables -A INPUT -p udp --dport 20000:30000 -j ACCEPT # 允许UDP协议的20000-30000端口
iptables -A INPUT -p tcp --dport 80 -j ACCEPT # 允许TCP协议的80端口
iptables -A INPUT -p tcp --dport 443 -j ACCEPT # 允许TCP协议的443端口
iptables -A INPUT -j DROP # 未匹配以上规则的请求直接丢弃
iptables -A OUTPUT -j ACCEPT # 允许全部出网数据包
iptables -A FORWARD -j DROP # 不允许Iptables的FORWARD转发
-I
与-A
的区别为前者始终在iptables
的开头添加规则,后者则是追加规则到iptables
的末尾
allow_ips.sh
#! /bin/bash
Green="\033[32m"
Red="\033[31m"
Font="\033[0m"
# 从ipdeny获取IP地址范围 空格隔开 e.g. cn jp
GEOIPS="cn"
TEMP="$GEOIPS cloudflare private domains"
# 需要放行的域名服务
domains="ipdeny.com download.docker.com registry.docker.io"
# 查询并收集IPv4地址
for domain in $domains; do
echo "查询域名:$domain"
nslookup "$domain" | awk '/^Address: / { print $2 }' | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' | grep -v ':' >> /tmp/domains.zone
done
# 下载GEOIP
for GEOIP in $GEOIPS; do
wget -P /tmp https://www.ipdeny.com/ipblocks/data/countries/$GEOIP.zone 2> /dev/null
if [ -f "/tmp/"$GEOIP".zone" ];then
echo -e "${Green}$GEOIP IPs data下载成功!${Font}"
else
echo -e "${Red}$GEOIP下载失败,请检查你的输入!${Font}"
echo -e "${Green}代码查看地址:http://www.ipdeny.com/ipblocks/data/countries/${Font}"
exit 1
fi
done
wget -O /tmp/cloudflare.zone https://www.cloudflare.com/ips-v4 2> /dev/null
if [ -f "/tmp/cloudflare.zone" ];then
echo -e "${Green}cloudflare IPs data下载成功!${Font}"
else
echo -e "${Red}cloudflare下载失败,请检查你的输入!${Font}"
echo -e "${Green}代码查看地址:https://www.cloudflare.com/ips-v4${Font}"
exit 1
fi
cat << 'EOF' > "/tmp/private.zone"
localhost
127.0.0.1
10.0.0.0/8
100.64.0.0/10
172.16.0.0/12
192.168.0.0/16
EOF
#创建规则
lookuplist=`ipset list | grep "Name:" | grep ALLOW_SET`
if [ -n "$lookuplist" ]; then
ipset flush ALLOW_SET
else
ipset -N ALLOW_SET hash:net
fi
# 销毁
# iptables -D INPUT -m set ! --match-set ALLOW_SET src -j DROP
# ipset destroy ALLOW_SET
# 设置iptables
for GEOIP in $TEMP; do
for i in $(cat /tmp/$GEOIP.zone ); do ipset -A ALLOW_SET $i; done
rm -f /tmp/$GEOIP.zone
echo -e "${Green}$GEOIP规则添加成功!${Font}"
done
# 仅允许ALLOW_SET访问
iptables -A INPUT -m set ! --match-set ALLOW_SET src -j DROP
echo "iptables规则已更新"
删除
iptables -D INPUT -m set ! --match-set ALLOW_SET src -j DROP
ipset destroy ALLOW_SET
定时更新iptables规则
sudo crontab -e
# 每周一凌晨更新
0 0 * * 1 /<you ptah>/allow_ips.sh
\color{red}{上述规则并不完善,仅放行了我常用的域名,需要根据自身需求调整上述脚本}