侧边栏壁纸
博主头像
汪洋

即使慢,驰而不息,纵会落后,纵会失败,但一定可以达到他所向的目标。 - 鲁迅

  • 累计撰写 175 篇文章
  • 累计创建 70 个标签
  • 累计收到 69 条评论

Linux 防御 CC 或 DDoS 攻击简单脚本文件

汪洋
2023-04-27 / 0 评论 / 0 点赞 / 61 阅读 / 6,671 字

今天给大家分享几个脚本案例,有使用 shell 编写的脚本也有使用 c 语言编写的脚本,Python 编写的脚本

一、基于 shell


要防御CC攻击,可以使用iptables和fail2ban等工具来实现。以下是一个用Shell脚本来配置iptables和fail2ban的示例:
#!/bin/bash
# 设置变量
port="80"  # 要保护的端口
threshold="10"  # CC攻击阈值
blocktime="60"  # 封禁时间(单位秒)
# 清除iptables规则
iptables -F
iptables -X
iptables -Z
# 允许本地回环地址
iptables -A INPUT -i lo -j ACCEPT
# 允许已建立的连接
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 开启SYN Flood防御
iptables -N syn_flood
iptables -A INPUT -p tcp --syn -j syn_flood
iptables -A syn_flood -m limit --limit 1/s --limit-burst 3 -j RETURN
iptables -A syn_flood -j DROP
# 防御CC攻击
iptables -A INPUT -p tcp --dport ${port} -m conntrack --ctstate NEW -m recent --set
iptables -A INPUT -p tcp --dport ${port} -m conntrack --ctstate NEW -m recent --update --seconds 1 --hitcount ${threshold} -j DROP
# 其他未授权访问防御
iptables -A INPUT -j REJECT --reject-with icmp-host-prohibited
# 安装fail2ban
apt-get install fail2ban -y
# 配置fail2ban
cat <<EOF > /etc/fail2ban/jail.local
[http-get-dos]
enabled = true
port = ${port}
filter = http-get-dos
logpath = /var/log/apache/access.log
findtime = 10
bantime = ${blocktime}
maxretry = ${threshold}
EOF
cat <<EOF > /etc/fail2ban/filter.d/http-get-dos.conf
[Definition]
failregex = ^<HOST> -.*"(GET|POST).*HTTP.*" 40\d.*$
ignoreregex =
EOF
# 重启服务
service iptables restart
service fail2ban restart
# 该脚本首先清除了iptables规则,然后添加了一些基础规则,如允许本地回环地址和已建立的连接。接着开启了SYN Flood防御和CC攻击防御,当某个IP在指定时间内达到一定的请求数(超过阈值),就会被iptables封禁。同时,该脚本还安装并配置了fail2ban,用于监控Apache访问日志中的HTTP请求,并将频繁访问的IP添加到iptables规则中进行防御。
# 需要注意的是,这只是一个示例脚本,实际应用时可能需要根据具体情况进行修改和优化。同时,在使用iptables和fail2ban等工具时,应仔细了解其原理和操作方法,避免误操作造成不必要的损失。

二、基于 C 语言

# 以下是一个简单的防御 CC 攻击和 DDoS 攻击 80 端口和 443 端口的脚本,使用 C 语言编写:
# 注意:此脚本只是提供一个基本的防御方法,具体的安全防护还需要根据实际情况进行定制化配置。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#define PORT 80
#define BUF_SIZE 1024
#define BACKLOG 10
#define MAX_EVENTS 100
#define MAX_CLIENTS 10
int epfd, listen_sock, client_sock[MAX_CLIENTS], max_fd;
struct epoll_event event, events[MAX_EVENTS];
char buf[BUF_SIZE];
int count = 0;
sig_atomic_t stop_signal;
void handle_signal(int sig) {
    stop_signal = 1;
}
void set_nonblocking(int sock) {
    int flags = fcntl(sock, F_GETFL, 0);
    if (flags == -1) {
        perror("fcntl");
        exit(1);
    }
    if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) {
        perror("fcntl");
        exit(1);
    }
}
int main() {
    struct sockaddr_in addr, client_addr;
    socklen_t client_addr_len;
    int i, n, fd, pid, reuseaddr_on = 1;
    // 创建监听socket
    listen_sock = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_sock == -1) {
        perror("socket");
        exit(1);
    }
    // 设置socket选项
    if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_on,
                   sizeof(reuseaddr_on)) == -1) {
        perror("setsockopt");
        exit(1);
    }
    // 绑定IP地址和端口号
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(PORT);
    if (bind(listen_sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
        perror("bind");
        exit(1);
    }
    // 监听端口
    if (listen(listen_sock, BACKLOG) == -1) {
        perror("listen");
        exit(1);
    }
    // 创建epoll实例
    epfd = epoll_create1(0);
    if (epfd == -1) {
        perror("epoll_create1");
        exit(1);
    }
    // 添加监听socket到epoll实例
    event.data.fd = listen_sock;
    event.events = EPOLLIN | EPOLLET;
    if (epoll_ctl(epfd, EPOLL_CTL_ADD, listen_sock, &event) == -1) {
        perror("epoll_ctl");
        exit(1);
    }
    max_fd = listen_sock;
    // 处理中断信号
    signal(SIGINT, handle_signal);
    signal(SIGTERM, handle_signal);
    // 开始循环,等待连接
    while (!stop_signal) {
        n = epoll_wait(epfd, events, MAX_EVENTS, -1);
        if (n == -1) {
            if (errno == EINTR) {
                continue;
            } else {
                perror("epoll_wait");
                exit(1);
            }
        }
        for (i = 0; i < n; i++) {
            // 处理新的连接请求
            if (events[i].data.fd == listen_sock) {
                while (1) {
                    client_addr_len = sizeof(client_addr);
                    fd = accept(listen_sock, (struct sockaddr *)&client_addr,
                                &client_addr_len);
                    if (fd == -1) {
                        if (errno == EAGAIN || errno == EWOULDBLOCK) {
                            break;
                        } else {
                            perror("accept");
                            break;
                        }
                    }
                    // 设置socket为非阻塞模式,并将其添加到epoll实例中
                    set_nonblocking(fd);
                    event.data.fd = fd;
                    event.events = EPOLLIN | EPOLLET;
                    if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event) == -1) {
                        perror("epoll_ctl");
                        exit(1);
                    }
                    max_fd = (max_fd > fd) ? max_fd : fd;
                    // 如果同时有太多连接,拒绝连接
                    count++;
                    if (count > MAX_CLIENTS) {
                        close(fd);
                    }
                }
            } else { // 处理现有连接
                fd = events[i].data.fd;
                memset(buf, 0, BUF_SIZE);
                while (1) {
                    n = recv(fd, buf, BUF_SIZE, 0);
                    if (n == -1) {
                        if (errno == EAGAIN || errno == EWOULDBLOCK) {
                            break;
                        } else {
                            perror("recv");
                            break;
                        }
                    } else if (n == 0) {
                        // 客户端关闭连接
                        close(fd);
                    } else {
                        // 处理收到的数据
                        if (strstr(buf, "GET /") != NULL ||
                            strstr(buf, "POST /") != NULL ||
                            strstr(buf, "HEAD /") != NULL ||
                            strstr(buf, "PUT /") != NULL ||
                            strstr(buf, "DELETE /") != NULL ||
                            strstr(buf, "OPTIONS /") != NULL ||
                            strstr(buf, "TRACE /") != NULL ||
                            strstr(buf, "CONNECT /") != NULL) {
                            // 如果请求包含HTTP协议相关动词,判断该请求是否来自攻击者
                            int port = ntohs(client_addr.sin_port);
                            if (port == 80 || port == 443) {
                                printf("Possible DDoS attack from %s:%d\n",
                                       inet_ntoa(client_addr.sin_addr),
                                       ntohs(client_addr.sin_port));
                                close(fd);
                            }
                        }
                    }
                }
            }
        }
    }
    // 清理资源
    close(listen_sock);
    for (i = 0; i < MAX_CLIENTS; i++) {
        if (client_sock[i] > 0) {
            close(client_sock[i]);
        }
    }
    return 0;
}

三、基于 shell

# 以下是一个自动防御 CC 和 DDoS 攻击的脚本,它将监视服务器上的连接,并拉黑任何尝试通过大量连接攻击服务器的IP地址。同时,它将所有拉黑的IP地址输出到一个文本文件中,以便管理员进行审计和管理。
#!/bin/bash
# 创建IP黑名单文件,如果不存在
BLACKLIST_FILE=/etc/blacklist.txt
touch $BLACKLIST_FILE
# 设置触发阈值
THRESHOLD=500
while true; do
  # 获取当前活跃的连接数
  CONNECTIONS=$(netstat -an | grep -E ':80|:443|:3306' | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n)
  # 检查是否有IP地址超过阈值
  while read line; do
    COUNT=$(echo $line | awk '{print $1}')
    IP=$(echo $line | awk '{print $2}')
    # 如果连接数大于阈值,则拉黑IP地址
    if [ $COUNT -gt $THRESHOLD ]; then
      if ! grep -q "$IP" "$BLACKLIST_FILE"; then
        echo "拉黑IP地址: $IP"
        echo "$IP" >> $BLACKLIST_FILE
        iptables -A INPUT -s $IP -j DROP
      fi
    fi
  done <<< "$CONNECTIONS"
  # 将拉黑的IP地址输出到ip.txt文本中
  cat $BLACKLIST_FILE > ip.txt
  # 等待30秒,然后重复循环
  sleep 30
done
# 请注意,这仅仅是一个简单的脚本,无法确保完全防止所有类型的攻击。建议使用专业的安全工具和技术来保护服务器免受攻击。同时,拉黑IP地址可能会对合法用户产生影响,因此可以根据需要进行调整。

四、基于 Python

# 以下是一个使用Python语言编写的自动防御CC和DDoS攻击的脚本,它将监视服务器上的连接,并拉黑任何尝试通过大量连接攻击服务器的IP地址。同时,它将所有拉黑的IP地址输出到一个文本文件中,以便管理员进行审计和管理。
#!/usr/bin/env python
import os
import time
# 创建IP黑名单文件,如果不存在
BLACKLIST_FILE = '/etc/blacklist.txt'
os.system('touch %s' % BLACKLIST_FILE)
# 设置触发阈值
THRESHOLD = 500
while True:
  # 获取当前活跃的连接数
  connections = {}
  with os.popen("netstat -an | grep ':80\|:443\|:3306' | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n") as f:
    for line in f:
      count, ip = line.split()
      connections[ip] = int(count)
  # 检查是否有IP地址超过阈值
  for ip, count in connections.items():
    if count > THRESHOLD:
      # 如果连接数大于阈值,则拉黑IP地址
      if not ip in open(BLACKLIST_FILE,'r').read():
        print '拉黑IP地址: %s' % ip
        with open(BLACKLIST_FILE, 'a') as f:
          f.write(ip + "\n")
        os.system('iptables -A INPUT -s %s -j DROP' % ip)
  # 将拉黑的IP地址输出到ip.txt文本中
  os.system('cp %s ip.txt' % BLACKLIST_FILE)
  # 等待30秒,然后重复循环
  time.sleep(30)
# 请注意,这仅仅是一个简单的脚本,无法确保完全防止所有类型的攻击。建议使用专业的安全工具和技术来保护服务器免受攻击。同时,拉黑IP地址可能会对合法用户产生影响,因此可以根据需要进行调整。
0

评论区