Total Pageviews

Tuesday 23 April 2013

linux vps如何防御SYN攻击

首先说一下SYN的攻击原理:  
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。
  
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
  
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
  
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。 完成三次握手,客户端与服务器开始传送数据.
如果用户与服务器发起连接请求只进行到第二次握手而不再响应服务器,服务器就会不停地等待用户的确认,如果过多这样的连接就会把服务器端的连接队列占满就会导致正常的用户无法建立连接。所以我们直接从SYN的连接上进行如下改动:
查看linux默认的syn配置:
  
[root@paulvps ~]# sysctl -a | grep _syn
  
net.ipv4.tcp_max_syn_backlog = 1024
  
net.ipv4.tcp_syncookies = 1
  
net.ipv4.tcp_synack_retries = 5
  
net.ipv4.tcp_syn_retries = 5

tcp_max_syn_backlog 是SYN队列的长度,加大SYN队列长度可以容纳更多等待连接的网络连接数。tcp_syncookies是一个开关,是否打开SYN Cookie 功能,该功能可以防止部分SYN攻击。tcp_synack_retries和tcp_syn_retries定义SYN 的重试连接次数,将默认的参数减小来控制SYN连接次数的尽量少。
  
以下是我修改后的参数,可以根据自己服务器的实际情况进行修改:
  
[root@paulvps ~]# more /etc/rc.d/rc.local
  
#!/bin/sh
  
# This script will be executed *after* all the other init scripts.
  
# You can put your own initialization stuff in here if you don't
  
# want to do the full Sys V style init stuff.
  
touch /var/lock/subsys/local
  
ulimit -HSn 65535
  
/usr/local/apache2/bin/apachectl start
  
#####
  
sysctl -w net.ipv4.tcp_max_syn_backlog=2048
  
sysctl -w net.ipv4.tcp_syncookies=1
  
sysctl -w net.ipv4.tcp_synack_retries=3
  
sysctl -w net.ipv4.tcp_syn_retries=3

为了不重启服务器而使配置立即生效,可以执行
  
#sysctl -w net.ipv4.tcp_max_syn_backlog=2048
  
#sysctl -w net.ipv4.tcp_syncookies=1
  
#sysctl -w net.ipv4.tcp_synack_retries=3
  
#sysctl -w net.ipv4.tcp_syn_retries=3

也有的人喜欢用访问控制列表来防止SYN的攻击,在一定程度上减缓了syn的攻击:
  
Syn 洪水攻击
  
#iptables -A INPUT -p tcp --syn -m limit --limit 1/s -j ACCEPT

--limit 1/s 限制syn并发数每秒1次
  
防端口扫描
  
# iptables -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j ACCEPT

死亡之ping
  
# iptables -A FORWARD -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT
  
#>iptables-save >/etc/sysconfig/iptables

进行查看,#iptables -L
  
ACCEPT tcp -- anywhere anywhere tcp flags:FIN,SYN,RST,ACK/SYN limit: avg 1/sec burst 5
  
ACCEPT tcp -- anywhere anywhere tcp flags:FIN,SYN,RST,ACK/RST limit: avg 1/sec burst 5
  
ACCEPT icmp -- anywhere anywhere icmp echo-request limit: avg 1/sec burst 5

再次进行查看syn连接:
  
[root@paulvps ~]# netstat -an | grep SYN | awk '{print $5}' | awk -F: '{print $1}' | sort | uniq -c | sort -nr | more

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

Linux 防止cc syn ack 攻击

三次握手的过程及相关概念
TCP/IP协议使用三次握手来建立连接,过程如下:
1、第一次握手,客户端发送数据包syn到服务器,并进入SYN_SEND状态,等待回复
2、第二次握手,服务器发送数据报syn/ack,给客户机,并进入SYN_RECV状态,等待回复
3、第三次握手,客户端发送数据包ACK给客户机,发送完成后,客户端和服务器进入ESTABLISHED状态,链接建立完成

三次握手协议中,服务器维护一个等待队列,收到一个syn包就在队列中建立一个条目,并分配一定的资源。对应的每一个条目表示已经收到一个syn请 求,并已经回复syn/ack,服务器上对应的连接已经进入SYN_RECV状态,等待客户端响应,收到客户端的响应包以后,该连接进入 ESTABLISHED状态,队列中对应的条目被删除。
backlog参数:设定等待队列的最大数目。对应内核参数:net.ipv4.tcp_max_syn_backlog = 1024
syn-ack重传次数:服务器发送syn/ack包,如果没有收到客户端的相应,就会重传syn/ack,超过一定时间之后会进行第二次重传,超过设定 次数以后将该条目从队列中删除。每次重传的间隔时间并不确定。对应的内核参数:net.ipv4.tcp_synack_retries = 5
syn重传次数:概念和syn/ack重传次数类似,对应的内核参数:net.ipv4.tcp_syn_retries = 5
等待存活时间:指等待队列的条目存活时间,即从服务器收到syn包到确认这个包无效的最长时间,该时间是所有重传包请求的最长等待时间

什么是SYN 攻击

syn攻击属于DDOS攻击中的一种,利用TCP/IP的缺陷进行网络攻击,可以使用很小的资源取得十分显著的效果。其基本原理如下:
服务器收到客户端的syn包,之后进入SYN_RECV状态,服务器的等待队列中增加一个条目,服务器未收到客户端的确认包,进行重传,一直到超时之后, 该条目从未链接队列中删除。客户端不断地发送syn包,而不响应来自服务器的syn/ack,等待队列的条目迅速增长,最后服务器的等待队列达到最大数 目,之后就不能再接受新的连接,一直到链接超时才从队列中删除对应的条目。配合ip地址欺骗技术,该方法可以取得十分良好的效果,基本上在攻击期间,服务 器将不能给正常的用户提供服务。这个攻击办法利用了TCP/IP协议的缺陷,攻击的目标不止于服务器,任何网络设备,只要开启了网络服务器,都可能会受到 这种攻击,导致处理器资源被大量占用,内存被用完,大量队列等待处理,针对网络设备的攻击往往会导致整个网络瘫痪。

如何减小SYN攻击的影响

1、修改等待数:

# sysctl -w net.ipv4.tcp_max_syn_backlog=2048

2、启用syncookies:

#sysctl -w net.ipv4.tcp_syncookies=1

启用syncookies可以大幅减小syn攻击带来的影响,但是却引入了新的安全缺陷

syncookie基本原理是:仔细处理连接的初始序列号而不是随机选择一个序列号。一旦server接收到SYN报文,将关键信息仔细编码并作为 state存储在SYN队列中。这种经过编码的信息是用一个秘钥进行加密hash,形成SYN-ACK报文中的序列号并发送给client。在合法握手的 第三个报文中,即从client返回给server的ACK报文中,在acknowledgment number字段中包含该序列号(加1). 这样,open双向连接所必须的所有信息又返回给server,而server在三次握手完成之前不必维护state。syn-cookies解决了 SYN的基本问题,但是随之带来一个新的问题,就是服务器需要对收到的ACK报文进行计算,提高了三次握手需要的系统资源。一种新的攻击方式随之而来,即 ACK攻击,发送大量的ACK数据报,导致服务器忙于计算最终导致服务器停止相应。Linux上的实际应用中,只有等待数被占满的时候才会启用 syncookies的方式(syncookies摘自网文)

3、修改重试次数

#sysctl -w net.ipv4.tcp_syn_retries = 0 重传次数设置为0,只要收不到客户端的响应,立即丢弃该连接,默认设置为5次

4、使用iptables限制单个地址的并发连接数量:

#iptables -t filter -A INPUT -p tcp --dport 80 --tcp-flags FIN,SYN,RST,ACK SYN -m connlimit --connlimit-above 10 --connlimit-mask 32 -j REJECT

5、使用iptables限制单个c类子网的并发链接数量:

#iptables -t filter -A INPUT -p tcp --dport 80 --tcp-flags FIN,SYN,RST,ACK SYN -m connlimit --connlimit-above 10 --connlimit-mask 24 -j REJECT

6、限制单位时间内的连接数:

#iptables -t filter -A INPUT -p tcp --dport 80 -m --state --state NEW -m recent --set --name access --resource  

#iptables -t filter -A INPUT -p tcp --dport 80 -m --state --state NEW -m recent --update --seconds 60 --hitcount 30 --name access -j DROP  

或者使用如下两条策略  

#iptables -t filter -A INPUT -p tcp --dport 80 -m --state --syn -m recent --set  

#iptables -t filter -A INPUT -p tcp --dport 80 -m --state --syn -m recent --update --seconds 60 --hitcount 30 -j DROP

7、为了取得更好的效果,需要修改/etc/modprobe.conf

options ipt_recent ip_list_tot=1000 ip_pkt_list_tot=60 记录10000个地址,每个地址60个包 # ip_list_tot最大为8100,超过这个数值会导致iptables错误

8、限制单个地址最大连接数:

#iptables -I INPUT -p tcp --dport 80 -m connlimit --connlimit-above 50 -j DROP  

应对 ACK攻击  

ACK 攻击是针对syn-cookies而发产生的,通过发送大量的ACK数据报,使目标服务器忙于计算,达到拒绝服务的目的,使用iptables对发起 ACK攻击的地址进行限制  

#iptables -I INPUT -p tcp --dport 80 -m connlimit --connlimit-above 50 -j DROP 限制并发连接数不大于50  

#iptables -t filter -A INPUT -p tcp --dport 80 --tcp-flags FIN,SYN,RST,ACK ACK -m connlimit --connlimit-above 10 --connlimit-mask 32 -j REJECT 限制并发ACK不大于50  


#iptables -t filter -A INPUT -p tcp --dport 80 --tcp-flags FIN,SYN,RST,ACK ACK -m recent --set --name drop  


#iptables -t filter -A INPUT -p tcp --dport 80 --tcp-flags FIN,SYN,RST,ACK ACK -m recent --update --seconds 60 --hitcount 30 -j DROP 一分钟内大于30次的连接全部丢弃

应对CC攻击

普通的CC攻击特点是所有的连接都是正常的完整的连接,这样的连接一般的防火墙是很难预防的。但是既然是网络攻击必然也具有网络攻击的共同特点,也 就是每一个攻击源都会发起尽量多的连接,因此我们仍然可以使用限制单个地址并发链接数量的办法来实现对CC攻击的抵御。具体命令同上

webcc,想必之下似乎更加难以预防,但是由于所有的访问都是由相同的一个或几个网站中转而来,这些访问请求的http_reffer都会带有这 些中转站的地址。我们只要在web服务器上设置http_reffer过滤即可大幅减小webcc攻击的影响,具体的设置这里就略过不表了

附:如何为RHEL5增加connlimit模块

#wget ftp://ftp.netfilter.org/pub/patch-o-matic-ng/snapshot/patch-o-matic-ng-20080214.tar.bz2  
#wget ftp://ftp.netfilter.org/pub/iptables/iptables-1.4.0.tar.bz2  
#  
bunzip2 iptables-1.4.0.tar.bz2    
#  
tar xvf iptables-1.4.0.tar    
#    
bunzip2 patch-o-matic-ng-20080214.tar.bz2    
# tar xf patch-o-matic-ng-20080214.tar    
#  
cd patch-o-matic-ng-20080214

下载connlimit模块

# export KERNEL_DIR=/usr/src/kernels/2.6.18-8.el5-i686/    
# export IPTABLES_DIR=/root/iptables-1.4.0  
# ./runme --download  

Successfully downloaded external patch geoip  
Successfully downloaded external patch condition  
Successfully downloaded external patch IPMARK  
Successfully downloaded external patch ROUTE  
Successfully downloaded external patch connlimit  
Successfully downloaded external patch ipp2p  
Successfully downloaded external patch time  
./patchlets/ipv4options exists and is not external  
./patchlets/TARPIT exists and is not external  
Failed to get http://www.intra2net.com/de/produkte/opensource/ipt_account//index, skipping..  
Successfully downloaded external patch pknock  
Loading patchlet definitions........................ done  


Excellent! Source trees are ready for compilation.

把connlimit应用到内核

# ./runme connlimit  
Loading patchlet definitions........................ done  
Welcome to Patch-o-matic ($Revision: 6736 $)!  

Kernel:  
2.6.18, /usr/src/kernels/2.6.18-8.el5-i686/  
Iptables: 1.4.0, /root/iptables-1.4.0/  
Each patch is a new feature: many have minimal impact, some do not.  
Almost every one has bugs, so don't apply what you don't need!  
-------------------------------------------------------  
Already applied:    
Testing connlimit... not applied  
The connlimit patch:  

Author: Gerd Knorr <kraxel@bytesex.org>  

Status: ItWorksForMe[tm]  

This adds an iptables match which allows you to restrict the  
number of parallel TCP connections to a server per client IP address  
(or address block).  

Examples:  

# allow 2 telnet connections per client host  
iptables -p tcp --syn --dport 23 -m connlimit --connlimit-above 2 -j REJECT  

# you can also match the other way around:  
iptables -p tcp --syn --dport 23 -m connlimit ! --connlimit-above 2 -j ACCEPT  

# limit the nr of parallel http requests to 16 per class C sized  
# network (24 bit netmask)  
iptables -p tcp --syn --dport 80 -m connlimit --connlimit-above 16 /  

--connlimit-mask 24 -j REJECT  
-----------------------------------------------------------------  
Do you want to apply this patch [N/y/t/f/a/r/b/w/q/?] y  

Excellent! Source trees are ready for compilation.  
内核编译
# make oldconfig  
scripts/kconfig/conf -o arch/i386/Kconfig  
*  
* Linux Kernel Configuration  
*  
*  
* Code maturity level options  
*  
Prompt for development and/or incomplete code/drivers (EXPERIMENTAL) [Y/n/?] y  

*  
* General setup  
………………………………………………………………………………………………………………………………………………………..  



ARP tables support (IP_NF_ARPTABLES) [M/n/?] m  

ARP packet filtering (IP_NF_ARPFILTER) [M/n/?] m  

ARP payload mangling (IP_NF_ARP_MANGLE) [M/n/?] m  

Connections/IP limit match support (IP_NF_MATCH_CONNLIMIT) [N/m/?] (NEW) m

提示加入了connlimit的选项,问使用哪一种模式,编译进内核还是模块,输入“m”,编译为模块

CRC16 functions (CRC16) [M/n/y/?] m  
CRC32 functions (CRC32) [Y/?] y  
CRC32c (Castagnoli, et al) Cyclic Redundancy-Check (LIBCRC32C) [Y/?] y  
#  
# configuration written to .config  
#

编译模块

# make modules_prepare  
scripts/kconfig/conf -s arch/i386/Kconfig  

CHK  
include/linux/version.h  

CHK  
include/linux/utsrelease.h  

HOSTCC  
scripts/genksyms/genksyms.o  

HOSTCC  
scripts/genksyms/lex.o  

HOSTCC  
scripts/genksyms/parse.o  

HOSTLD  
scripts/genksyms/genksyms  

CC  
scripts/mod/empty.o  

MKELF  
scripts/mod/elfconfig.h  

HOSTCC  
scripts/mod/file2alias.o  

HOSTCC  
scripts/mod/modpost.o  

HOSTCC  
scripts/mod/sumversion.o  

HOSTLD  
scripts/mod/modpost
[root@localhost 2.6.18-8.el5-i686]# mv net/ipv4/netfilter/Makefile    
net/ipv4/netfilter/Makefile.bak

备份原来的文件

# make M=net/ipv4/netfilter/  

LD  
net/ipv4/netfilter/built-in.o  

CC [M]  
net/ipv4/netfilter/ipt_connlimit.o  

Building modules, stage 2.  

MODPOST  

CC  
net/ipv4/netfilter/ipt_connlimit.mod.o  

LD [M]  
net/ipv4/netfilter/ipt_connlimit.ko  

#  
cp net/ipv4/netfilter/ipt_connlimit.ko /lib/modules/2.6.18-8.el5/kernel/net/ipv4/netfilter/  
# chmod 744 /lib/modules/2.6.18-8.el5/kernel/net/ipv4/netfilter/ipt_connlimit.ko    

# depmod -a  
[root@localhost 2.6.18-8.el5-i686]# modprobe ipt_connlimit  
# lsmod |grep conn  
ip_conntrack_netbios_ns  
6977  
0    
ipt_connlimit  
7680  
6    
ip_conntrack  
53153  
3 ip_conntrack_netbios_ns,xt_state,ipt_connlimit  
nfnetlink  
10713  
1 ip_conntrack  
x_tables  
17349  
8 ipt_recent,xt_state,ipt_REJECT,ipt_connlimit,ip_tables,ip6t_REJECT,xt_tcpudp,ip6_tables

好了,模块安装完毕。可以使用connlimit策略了.