Linux防火墙管理脚本,自动屏蔽网络威胁IP

Linux系统
371
0
0
2023-03-11
分享一个自己写来管理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