分享一个自己写来管理firewall防火墙的脚本,主要通过抓取几个IP黑名单的网站源并列入IPSet规则进行限制,通过计划任务定期执行脚本更新,能一定程度上预防端口扫描和隔绝网络威胁等恶意行为。
注意事项
写这个脚本的时候有一段时间了,那个时候技术水平有限,脚本不是很严谨,但功能不受影响,目前也是一直用到了现在没有出过任何问题,主要注意一些参数的设定就可以了,有空随缘再优化完善咯。
1、仅适用于 Linux Debian 系统,但仅是考虑系统环境不一致看得懂的话改改也不难;
2、使用前先确保系统安装好了 iptables 与 ipset ;
3、程序通过两个脚本实现,BlackIP.sh 用于更新 ipset ,iptables.sh 用于更新iptables ;
4、第一次使用需要先运行 BlackIP.sh ;
5、如果安装了 Docker 需要删除在 BlackIP.sh 脚本最末端的注释。
配置说明
iptables.sh 变量
用于更新 iptables 规则,可添加自定义规则,运行一次后会在 if-pre-up.d 生成连接文件
#iptables.sh 脚本配置
IPT="/sbin/iptables" #iptables执行文件
SHELL_NetworkUP="/etc/network/if-pre-up.d/iptables_shell" #开机运行的连接文件
BIN_Docker="/bin/docker" #docker的执行文件,用于重启docker
IPSet_Shell="/root/shell/BlackIP.sh" #BlackIP.sh 脚本的绝对路径
BlackIP.sh 变量
用于更新 ipset 规则,由 Crontab 定时调用使用
#输出其他系统使用的文件
#脚本预配置了RouterOS系统和OpenClash系统使用的防火墙规则文件,填写了webfolder路径变量后更新时会生成文件
webfolder=
rosname="BlacklistData"
opname="OpenClash"
#IPSet使用的集名称
IPSetlist="Rblacklist"
#cache是获取网络黑名单的原内容
cache="/tmp/blacklist.cache"
#iplist是经过去重整理的内容
iplist="/tmp/BlackCIDR"
脚本源
iptables.sh
示例文件路径:/root/shell/iptables.sh
脚本运行方式:第一次运行,每次更新脚本内容后手动运行
脚本运行命令:/root/shell/iptables.sh
#!/bin/bash
#
# docker 开放的端口无需再次放行
#
#手动执行,脚本自动创建网络自启
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
IPT="/sbin/iptables"
SHELL_NetworkUP="/etc/network/if-pre-up.d/iptables_shell"
BIN_Docker="/bin/docker"
IPSet_Shell="/root/shell/BlackIP.sh"
#环境检查
if [ -z "`egrep -i "debian" /etc/issue`" ];then
echo "Sorry,iptables script only support debian system now."
exit 1
fi
# 获取SSH端口
if grep "^Port" /etc/ssh/sshd_config>/dev/null;then
sshdport=`grep "^Port" /etc/ssh/sshd_config | sed "s/Port\s//g" `
else
sshdport=22
fi
# 恢复链的默认策略
$IPT -P INPUT ACCEPT
$IPT -P FORWARD DROP
$IPT -P OUTPUT ACCEPT
# 清空INPUT/FORWARD/OUTPUT链
$IPT -F INPUT
$IPT -F FORWARD
$IPT -F OUTPUT
#运行IPSet脚本生成数据集并导入数据
nohup $IPSet_Shell iptables > /tmp/IPSet_Shell_UP.log 2>&1 &
# 允许已建立的或相关连接的通行
$IPT -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
$IPT -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
#这里可以新增规则,更改脚本内容后需再次运行脚本或重启生效
# 允许ping
#$IPT -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
#$IPT -A INPUT -p icmp -m icmp --icmp-type 11 -j ACCEPT
# 限制端口单个IP的最大连接数为10
#$IPT -I INPUT -p tcp --dport 80 -m connlimit --connlimit-above 5 -j DROP
#$IPT -I INPUT -p tcp --dport 443 -m connlimit --connlimit-above 10 -j DROP
# 允许SSH端口的连接,脚本自动侦测目前的SSH端口,否则默认为22端口
$IPT -A INPUT -p tcp -m tcp --dport $sshdport -j ACCEPT
# 允许80(HTTP)/443(HTTPS)端口的连接
#$IPT -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
#$IPT -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
# 允许DNS
for nameserver in `cat /etc/resolv.conf |grep nameserver |awk '{print $2 }'`
do
[ ! -z "$nameserver" ] && $IPT -A OUTPUT -p udp -m udp -d $nameserver --dport 53 -j ACCEPT
done
# 禁止进,允许出,允许回环网卡
$IPT -P INPUT DROP
$IPT -P FORWARD DROP
$IPT -P OUTPUT ACCEPT
$IPT -A INPUT -i lo -j ACCEPT #允许回环网卡
if [ "$SHELL_NetworkUP" = "$0" ];then
#脚本是由开机自动执行的,不链接自启文件
echo $0": Restore Firewall Rules."
else
#将脚本文件链接到开机网络启动后自运行
echo $0": Set Recovery Script."
if [ -f $SHELL_NetworkUP ];then
rm -r $SHELL_NetworkUP
fi
ln -s $0 $SHELL_NetworkUP
fi
BlackIP.sh
示例脚本路径:/root/shell/BlackIP.sh
脚本运行方式:添加至 crontab 定期运行更新
脚本运行命令:/bin/nohup /root/shell/BlackIP.sh > /tmp/IPSet_Shell_Cron.log 2>&1 &
#!/bin/bash
#脚本计划任务运行更新
#输出其他系统使用的文件
webfolder=
rosname="BlacklistData"
opname="OpenClash"
#IPSet集使用的名称
IPSetlist="Rblacklist"
time=$(date "+%H:%M:%S")
date=$(date "+%Y-%m-%d")
err=0
count=0
cache="/tmp/blacklist.cache"
iplist="/tmp/BlackCIDR"
#获取IP列表
echo "Get Blacklist:"
#中国科技大学网络威胁中心
count=$(($count+1))
echo -n "blackip.ustc.edu.cn"
curl -s --retry 5 --connect-timeout 3 http://blackip.ustc.edu.cn/list.php?txt |sed -e 's/\r//' -e '/^#.*/d' |grep -E -o '([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]{1,2}' >$cache
if [ $? -ne 0 ]; then echo -e " >> Failed ";err=$(($err+1)); else echo -e " >> Succeed ";fi
#CINS网络威胁中心
count=$(($count+1))
echo -n "cinsarmy.com"
curl -s --retry 5 --connect-timeout 3 https://cinsarmy.com/list/ci-badguys.txt |sed -e 's/\r//' -e '/^#.*/d' -e '/\.0$/d' |grep -E -o '([0-9]{1,3}\.){3}[0-9]{1,3}' |sed -e 's/$/\/32/g' >>$cache
if [ $? -ne 0 ]; then echo -e " >> Failed ";err=$(($err+1)); else echo -e " >> Succeed ";fi
#abuse.ch网络威胁中心
count=$(($count+1))
echo -n "feodotracker.abuse.ch"
curl -s --retry 5 --connect-timeout 3 https://feodotracker.abuse.ch/downloads/ipblocklist_recommended.txt |sed -e 's/\r//' -e '/^#.*/d' |grep -E -o '([0-9]{1,3}\.){3}[0-9]{1,3}' |sed -e 's/$/\/32/g' >>$cache
if [ $? -ne 0 ]; then echo -e " >> Failed ";err=$(($err+1)); else echo -e " >> Succeed ";fi
#abuse.ch虚假SSL证书
count=$(($count+1))
echo -n "sslbl.abuse.ch"
curl -s --retry 5 --connect-timeout 3 https://sslbl.abuse.ch/blacklist/sslipblacklist.txt |sed -e 's/\r//' -e '/^#.*/d' |grep -E -o '([0-9]{1,3}\.){3}[0-9]{1,3}' |sed -e 's/$/\/32/g' >>$cache
if [ $? -ne 0 ]; then echo -e " >> Failed ";err=$(($err+1)); else echo -e " >> Succeed ";fi
#emergingthreats网络威胁中心
count=$(($count+1))
echo -n "rules.emergingthreats.net"
curl -s --retry 5 --connect-timeout 3 https://rules.emergingthreats.net/fwrules/emerging-Block-IPs.txt |sed -e 's/\r//' -e '/^#.*/d' |grep -E -o '([0-9]{1,3}\.){3}[0-9]{1,3}' |sed -e 's/$/\/32/g' >>$cache
if [ $? -ne 0 ]; then echo -e " >> Failed ";err=$(($err+1)); else echo -e " >> Succeed ";fi
#BlockList网络威胁中心(大数据)
count=$(($count+1))
echo -n "lists.blocklist.de"
curl -s --retry 5 --connect-timeout 3 https://lists.blocklist.de/lists/all.txt |sed -e 's/\r//' -e '/^#.*/d' -e '/\.0$/d' |grep -E -o '([0-9]{1,3}\.){3}[0-9]{1,3}' |sed -e 's/$/\/32/g' >>$cache
if [ $? -ne 0 ]; then echo -e " >> Failed ";err=$(($err+1)); else echo -e " >> Succeed ";fi
#azorult-tracker恶意软件
count=$(($count+1))
echo -n "azorult-tracker.net"
curl -s --retry 5 --connect-timeout 3 https://azorult-tracker.net/api/list/ip?format=plain |sed -e 's/\r//' -e '/^#.*/d' -e '/\.0$/d' |grep -E -o '([0-9]{1,3}\.){3}[0-9]{1,3}' |sed -e 's/$/\/32/g' >>$cache
if [ $? -ne 0 ]; then echo -e " >> Failed ";err=$(($err+1)); else echo -e " >> Succeed ";fi
#输出状态
echo -e 'Date:'$date' Time:'$time'| Succeed:'$count' Failed:'$err
#若所有列表都获取失败则不执行
if [ $err -lt $count ]; then
#去重
sort -u $cache > $iplist
#输出文件 ebfolder变量为空不生成
if [ "$webfolder" != "" ]; then
echo "Generate:"
#Out RouterOS File
echo -n "Generate RouterOS Import File"
cat $iplist |sed -e '/\.0\/32$/d' |sed -e 's/^/add address=/g' -e 's/$/ list='$rosname'/g'|sed -e $'1i\\\n/ip firewall address-list' -e $'1i\\\nremove [/ip firewall address-list find list='$rosname']' |sed '$a \/' |sed '$a /file remove '$rosname'.rsc'>$webfolder/$rosname
if [ $? -ne 0 ]; then echo -e " >> Failed ";err=$(($err+1)); else echo -e " >> Succeed ";fi
#Out OpenClash File
echo -n "Generate OpenClash Import File"
cat $iplist |sed -e '/\.0\/32$/d' |sed -e 's/^/ - /g' |sed -e $'1i\\\npayload:'>$webfolder/$opname
if [ $? -ne 0 ]; then echo -e " >> Failed ";err=$(($err+1)); else echo -e " >> Succeed ";fi
fi
#更新 ipset 数据 (debian)
if [ -f "/sbin/ipset" ] && [ ! -z "`egrep -i "debian" /etc/issue`" ];then
echo "Set IPSet:"
#判断并创建集合
/sbin/ipset list $IPSetlist >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo -n "Establish IPSet list"$IPSetlist
/sbin/ipset create $IPSetlist hash:net maxelem 4294967295
if [ $? -ne 0 ]; then echo -e " >> Failed ";err=$(($err+1)); else echo -e " >> Succeed ";fi
fi
#清空集合内容
echo -n "Flush IPSet "$IPSetlist" list"
/sbin/ipset flush $IPSetlist >/dev/null 2>&1
if [ $? -ne 0 ]; then echo -e " >> Failed ";err=$(($err+1)); else echo -e " >> Succeed ";fi
#将数据循环导入集合
echo -n "Import "$IPSetlist" To IPSet"
while read ip; do
ipset add $IPSetlist $ip >/dev/null 2>&1
done < $iplist
if [ $? -ne 0 ]; then echo -e " >> Failed ";err=$(($err+1)); else echo -e " >> Succeed ";fi
fi
else
#所有列表都读取失败
echo -e " >> All List Get Failed! "
fi
#防火墙规则导入(由传参控制 $1=iptables )
#由iptables.sh脚本调用,既开机才调用
if [ "$1" == "iptables" ]; then
echo -n "Set IPSet iptables rule"
#读出现防火墙数据判断是否重复添加规则
IPTABLES=$(iptables-save)
if ! echo $IPTABLES|grep -q "\-A\ INPUT\ \-m\ set\ \-\-match\-set\ $IPSetlist\ src\ \-\j\ DROP"; then
#iptables -A INPUT -m set --match-set $IPSetlist src -j ULOG --ulog-prefix "Blocked input $IPSetlist"
#iptables -A FORWARD -m set --match-set $IPSetlist src -j ULOG --ulog-prefix "Blocked fwd $IPSetlist"
#iptables -A FORWARD -m set --match-set $IPSetlist dst -j ULOG --ulog-prefix "Blocked fwd $IPSetlist"
#iptables -A OUTPUT -m set --match-set $IPSetlist dst -j ULOG --ulog-prefix "Blocked out $IPSetlist"
iptables -I INPUT -m set --match-set $IPSetlist src -j DROP
iptables -I FORWARD -m set --match-set $IPSetlist src -j DROP
iptables -I FORWARD -m set --match-set $IPSetlist dst -j REJECT
iptables -I OUTPUT -m set --match-set $IPSetlist dst -j REJECT
if [ $? -ne 0 ]; then echo -e " >> Failed ";err=$(($err+1)); else echo -e " >> Succeed ";fi
#更新防火墙规则时,若Docker已在运行则需要重启Docker(安装了Docker删除下面的“#”)
#if [ "$(/bin/systemctl is-active docker)" = "active" ];then
# echo -n $0": Restart Docker Service"
# /bin/systemctl restart docker
# if [ $? -ne 0 ]; then echo -e " >> Failed ";err=$(($err+1)); else echo -e " >> Succeed ";fi
#fi
else
echo -e " >> Existence "
fi
fi