Python开发之DOS攻击检测和防御

Python检测和防御DOS攻击

利用Python编程实现对wrk的泛洪攻击检测,并让程序触发调用Linux命令实现防御:

1、泛洪攻击的检测,可以考虑使用的命令,这些命令可以通过Pytho调用和分析。

  • netstat -ant | wc -l
  • netstat -ant | grep SYN_RECV
  • netstat -s | grep overflowed
  • netstat -s | grep dropped
  • top -n 获取CPU使用率

以上操作过程的命令,允许使用管道和AWK提取数据,也可以直接使用Python进行数据提取

2、防御措施可以选择一下几种:

  • 修改系统配置参数,来增强系统的TCP连接数
  • 直接结束某些消耗CPU的进程,或者停止Apache的服务(不得已而为之)
  • 开启防火墙,将目标IP地址进行封锁(首选)
  • 自行查阅资料,进行其他可以执行的操作
  • 上述Python代码实现的狠心就是调用系统指令,再通过Python 进行分析,触发命令的执行等。建议在Linux上安装Pyotn3.x及以上的版本

基本步骤:

1、确保在Linux上可以正常运行Python3.x,而Centos内置的是python2.7版本

image-20240517192044187

2、做基本的调研,明确对于DOS的入侵检测,需要使用那些方法或命令

3、将可以使用的命令通过Python来运行,并进行调试,确保 Python+命令 可以正常运行

4、想办法找到连接数最多的攻击源IP地址,驱动Linux的防火墙进行入侵防御

5、最后进行整合,测试,再模拟攻击,确保脚本可以正常检测

一、在CentOS上安装Python3

下载地址:Python 版本 Python 3.10.14 |Python.org

安装教程:

CentOS 7 安装 Python 3.10_yum python3.10-CSDN博客

服务器Centos7部署安装Python3的完整过程(3.10.1) - 知乎 (zhihu.com)

cd ~

sudo yum -y update

sudo yum -y install openssl-devel libffi-devel bzip2-devel

sudo yum -y groupinstall "Development Tools"

wget https://www.openssl.org/source/openssl-1.1.1q.tar.gz --no-check-certificate

tar zxf openssl-1.1.1q.tar.gz

cd openssl-1.1.1q

./config --prefix=/usr/local/openssl-1.1.1

sudo make && sudo make install

mkdir /usr/local/python3

wget https://www.python.org/ftp/python/3.10.5/Python-3.10.5.tgz

tar zxf Python-3.10.5.tgz 

cd Python-3.10.5

./configure --enable-optimizations --with-openssl=/usr/local/openssl-1.1.1 --with-openssl-rpath=auto --prefix=/usr/local/python3

sudo make altinstall

#make

#make install

# 配置环境变量

vi ~/.bash_profile

export PYTHON_HOME=/usr/local/python3

PATH=$PATH:$HOME/bin:$PYTHON_HOME/bin

export PATH

退出编辑
source ~/.bash_profile

二、理解各个命令的含义

1、uptime

uptime 命令用户查看主机的开机时长,用户连接数量,以及在 1、5、15分钟 三个时间段内,CPU的负载情况

uptime

每周一个linux命令之—uptime详解 - vinter_he - 博客园 (cnblogs.com)

2、netstat

netstat 命令用来打印Linux中网络系统的状态信息,可让你得知整个Linux操作系统的网络情况,需要注意的是在windows和Linux上的参数会略有不同。

-a或--all 显示所有连线中的Socket
-n或--numeric 直接使用IP地址,而不通过域名服务器。意思就是以数字的形式代替服务
-l或--listening 显示监控中的服务器的Socket。
-t或--tcp 显示TCP传输协议的连线状况
-u或--udp 显示UDP传输协议的连线状况。
-s或--statistics 显示网络工作信息统计表
-r或--route 显示Routing Table。
-p或--programs 显示正在使用Socket的程序识别码和程序名称。

以数字方式列出所有TCP连接情况: netstat -ant
以数字方式列出所有UDP连接情况: netstat -anu
以数字方式列出所有TCP和UDP处理监听状态的情况: netstat -anult
显示所有端口的统计信息: netstat-s
显示TCP端口的统计信息: netstat-st
显示核心路由信息: netstat -r
显示所有连接的进程信息: netstat -ap

Linux netstat命令 |菜鸟教程 (runoob.com)

3、ss

ss 用来显示处于活动状态的套接字信息。他可以显示和netstat类似的内容,但ss的优势在于它能够显示更多更详细的有关TCP和连接状态的信息,而且比netstat更快速高效。

显示监听状态下的队列情况: ss -lnt
显示非监听状态下的连接详情: ss -nt
显示socket摘要信息: ss -s  注意其结果的IPv6的变化

LISTEN 状态: Recv-Q 表示的当前等待服务端调用 accept 完成三次握手的 listen backlog 数值,也就是说,当客户端通过 connect() 去连接正在 listen() 的服务端时,这些连接会一直处于这个 queue 里面直到被服务端accept() ; Send-Q 表示的则是最大的 listen backlog 数值,这就就是上面提到的 min(backlog,somaxconn)的值

非 LISTEN 状态: Recv-Q 表示 receive queue 中的 bytes 数量;Send-Q 表示 send queue 中的 bytes 数值该数值意义不大,更多关注连接的数量和状态即可

4、firewall-cmd

关闭防火墙:systemctl stop firewalld

添加允许端口:firewall-cmd --add-port=80/tcp

列出防火墙规则:firewall-cmd --list-all

禁止IP地址访问80端口:firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.168.112.148" port port="80" protocol="tcp" reject'

让配置永久生效:添加允许端口:firewall-cmd --add-port=80/tcp --permanent

允许http服务通过1分钟:firewall-cmd --zone=public --add-service=http --timeout=1m,这个 timeout 选项是一个以秒(s)、分(m)或小时(h)为单位的时间值。

5、sysctl

sysctl命令用于运行时配置内核参数,这些参数位于/proc/sys目录下。sysctl配置与显示在/proc/sys目录中的内核参数,可以用sysctl来设置或重新设置联网功能,如IP转发、IP碎片去除以及源路由检查等。用户只需要编辑/etc/sysctl.con文件,即可手工或自动执行由sysctl控制的功能。

显示所有系统参数:sysctl -a

使用cat查看指定参数:cat /proc/sys/net/ipv4/ip_forward,除/proc/sys外,后面的路径与参数名称一致换成 / 即可

临时改变某个指定参数的值,如:sysctl -w net.ipv4.ip forward=1,也可以:echo 1 > /proc/sys/netipv4/ip forward

如果想永久保留配置,可以修改/etc/sysctl.con文件

快速修改部分参数,优化性能:

net/ipv4/tcp_syn_cookies   是否打开SYN COOKIES的功能,"1”为打开,“2”关闭。

net/ipv4/tcp_max_syn_backlog	SYN队列的长度,加大队列长度可以容纳更多等待连接的网络连接数。

net/ipv4/tcp_synack_retries和net/ipv4/tcp_syn_retries	定义SYN重试次数,默认为5,建议为2

net/ipv4/sack=0

其他参数的说明:https://www.cnblogs.com/feiyun126/p/8646989.html

一些优化方案:https://blog.csdn.net/wangshuminjava/article/details/80935792

三、利用python实现DOS入侵检测

采集TCP连接数据

采集跟DOS攻击关联度较高的数据
uptime
  • 19:51:11 up 5 days, 8:40, 3 users, load average: 0.00, 0.02, 0.05 -> [’ 19:51:11 up 5 days’, ’ 8:40’, ’ 3 users’, ’ load average: 0.00’, ’ 0.02’, ’ 0.05\n’] -> load average: 0.00 -> [‘’, ‘’, ‘load’, ‘average:’, ‘0.00’] -> 0.00

import os,time

# 可采用 split和awk进行修改得到前1分钟的CPU平均负载
import time,os

def get_cpu_01():
    uptime = os.popen('uptime').read()
    #print(type(uptime))
    #print(uptime)
    cpu_load = float(uptime.split(',')[3].split(' ')[4])
    #print(cpu_load)
    return cpu_load

  • 20:07:30 up 5 days, 8:56, 3 users, load average: 0.00, 0.01, 0.05 –>> 20:07:30 up 5 days, 8:56, 3 users, load average,0.00, 0.01, 0.05 **–>> ** [’ 20:07:48 up 5 days’, ’ 8:56’, ’ 3 users’, ’ load average’, ‘0.00’, ’ 0.01’, ’ 0.05\n’] –>> 0.00

def get_cpu_02():
    uptime = os.popen('uptime').read()
    #print(type(uptime))
    #print(uptime)
    cpu_load = float(uptime.replace(': ',',').split(',')[4])
    #print(cpu_load)
    return cpu_load
  • 20:16:56 up 5 days, 9:05, 3 users, load average: 0.00, 0.01, 0.05 –>> 0.00, 0.01, 0.05 –>> 0.00

def get_cpu_03():
    uptime = os.popen('uptime').read()
    #print(type(uptime))
    #print(uptime)
    cpu_load = float(os.popen("uptime | awk -F ': ' '{print$2}' | awk -F ',' '{print$1}'").read())
    #print(cpu_load)
    return cpu_load
netstat -ant 连接数量

正常 netstat -ant 展示情况,一般是不会迅猛增加

image-20240521174617885

def get_TCP_conn():
    netstat = int(os.popen('netstat -ant | wc -l').read())
    return netstat
ss -lnt 读取队列情况

image-20240522201335571

def get_queue_size():
    queue = os.popen('ss -lnt | grep :80').read()
    recv_q = int(queue.split()[1])
    send_q = int(queue.split()[2])
    return recv_q,send_q
主调函数
if __name__ == '__main__':
    while True:
        #cpu_load = get_cpu_load_01()
        #cpu_load = get_cpu_load_02()
        cpu_load = get_cpu_load_03()

        TCP_conn = get_TCP_conn()

        recv_q,send_q = get_queue_size()

        print(f"cpu_load:{cpu_load} TCP_conn:{TCP_conn} TCP_Queue:{recv_q,send_q}")
        time.sleep(2)
        #print(type())
        if cpu_load > 33.3 or TCP_conn > 2000 or recv_q > send_q -10:
            print("CPU 负载过高或TCP连接数太多,可能遭遇DOS攻击,请注意!!!")

四、利用IP查询实现DOS防御

要实现DOS防御,除了能够检测到DOS攻击,必须还要对检测到的情况进行防御

对连接数量超标的ip地址进行封禁

  • 找到连接数量超标的IP地址
    • 通过执行 netstat -ant 我们可以查看tcp连接情况,然后再通过grep和其他处理方式找到所有连接我们的IP地址
    • 对所有连接本地服务器的IP地址进行处理,利用字典的特性可以统计每一个IP地址连接本地服务器的数量,找到超标的IP地址,执行防火墙将其封禁
def get_most_ip_basic():
    netstat = os.popen('netstat -ant | findstr :80').read()
    netstat_list = netstat.split('\n')
    ip_list=[]
    for line in netstat_list:
        try:
            ip = line.split()[2].split(':')[0]
            ip_list.append(ip)
            #print(ip)
        except:
            pass

    ip_dict = {}
    for ip in ip_list:
        if ip in ip_dict.keys():
            ip_dict[ip] += 1
        else:
            ip_dict[ip] = 1
    # print(ip_dict)
    # 默认对可迭代变量进行升序排序,所以改为降序排列
    sort = sorted(ip_dict.values(),reverse=True)
    # print(sort)
    for key,value in ip_dict.items():
        if value == sort[0]:
            return key,value

上面代码适合windows运行,下面适合linux运行

def get_most_ip():
    netstat = os.popen('netstat -ant | grep :80').read()
    netstat_list = netstat.split('\n')
    ip_list=[]
    for line in netstat_list:
        try:
            ip = line.split()[4].split(':')[0]
            ip_list.append(ip)
            #print(ip)
        except:
            pass
    # 直接使用Python内置的计数器来实现排序
    ip_dict = Counter(ip_list)
    most_ip = ip_dict.most_common(1)
    # print(most_ip)
    # print(type(most_ip))  # <class 'list'>
    return most_ip

主调函数

if __name__ == '__main__':
    while True:
        #cpu_load = get_cpu_load_01()
        #cpu_load = get_cpu_load_02()
        cpu_load = get_cpu_load_03()

        TCP_conn = get_TCP_conn()

        recv_q,send_q = get_queue_size()

        print(f"cpu_load:{cpu_load} TCP_conn:{TCP_conn} TCP_Queue:{recv_q,send_q}")
        time.sleep(2)
        #print(type())
        if cpu_load > 33.3 or TCP_conn > 2000 or recv_q > send_q -10:
            print("CPU 负载过高或TCP连接数太多,可能遭遇DOS攻击,请注意!!!")
            most_ip = get_most_ip()
            print(f"出现可疑IP:{most_ip[0][0]} 具有连接数:{most_ip[0][1]} ")
            firewall_mostip(most_ip[0][0])

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值