这里只讲“加固tcp/ip协议栈中的SynAttackProtect机制”这种方法。详细描述请见
http://blog.csdn.net/luojunjing/archive/2005/02/12/286333.aspx。
防范SYN攻击的另一项主要技术是调整tcp/ip协议栈,修改tcp协议实现。主要方法有SynAttackProtect保护机制、SYN cookies技术、增加最大半连接和缩短超时时间等。tcp/ip协议栈的调整可能会引起某些功能的受限,管理员应该在进行充分了解和测试的前提下进行此项工作。
■SynAttackProtect机制
为防范SYN攻击,win2000系统的tcp/ip协议栈内嵌了SynAttackProtect机制,Win2003系统也采用此机制。SynAttackProtect机制是通过关闭某些socket选项,增加额外的连接指示和减少超时时间,使系统能处理更多的SYN连接,以达到防范SYN攻击的目的。默认情况下,Win2000操作系统并不支持SynAttackProtect保护机制,需要在注册表以下位置增加SynAttackProtect键值:
HKLM/SYSTEM/CurrentControlSet/Services/Tcpip/Parameters
当SynAttackProtect值(如无特别说明,本文提到的注册表键值都为十六进制)为0或不设置时,系统不受SynAttackProtect保护。
当SynAttackProtect值为1时,系统通过减少重传次数和延迟未连接时路由缓冲项(route cache entry)防范SYN攻击。
当SynAttackProtect值为2时(Microsoft推荐使用此值),系统不仅使用backlog队列,还使用附加的半连接指示,以此来处理更多的SYN连接,使用此键值时,tcp/ip的TCPInitialRTT、window size和可滑动窗囗将被禁止。
我们应该知道,平时,系统是不启用SynAttackProtect机制的,仅在检测到SYN攻击时,才启用,并调整tcp/ip协议栈。那么系统是如何检测SYN攻击发生的呢?事实上,系统根据TcpMaxHalfOpen,TcpMaxHalfOpenRetried和TcpMaxPortsExhausted三个参数判断是否遭受SYN攻击。
TcpMaxHalfOpen表示能同时处理的最大半连接数(也即服务器处于SYN_RECV阶段),如果超过此值,系统认为正处于SYN攻击中。Win2000 server默认值为100,Win2000 Advanced server为500。
TcpMaxHalfOpenRetried定义了保存在backlog队列且重传过的半连接数(即服务器处于SYN_RECV阶段,并且对于一些连接,若发送了SYN-ACK后没有响应使得服务器重发SYN-ACK),如果超过此值,系统自动启动SynAttackProtect机制。Win2000 server默认值为80,Win2000 Advanced server为400。
TcpMaxPortsExhausted 是指系统拒绝的SYN请求包的数量(也即服务器处于LISTEN阶段,个人认为是与socket中的listen第二个参数backlog一样的意思,也即等待连接队列的长度),默认是5。
如果想调整以上参数的默认值,可以在注册表里修改(位置与SynAttackProtect相同)
附上MSDN中的专题《如何:强化 TCP/IP 堆栈安全》
http://www.microsoft.com/china/technet/security/guidance/secmod109.mspx#EPC
启用 SYN攻击保护
启用 SYN攻击保护的命名值位于此注册表项的下面:HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services。
值名称:SynAttackProtect
建议值: 2
有效值: 0 – 2
说明:使TCP 调整 SYN-ACK的重传。配置此值后,在遇到 SYN攻击时,对连接超时的响应将更快速。在超过TcpMaxHalfOpen 或TcpMaxHalfOpenRetried的值后,将触发 SYN攻击保护。
设置 SYN保护阈值
下列值确定触发 SYN保护的阈值。这一部分中的所有注册表项和值都位于注册表项HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services的下面。这些注册表项和值是:
• |
值名称:TcpMaxPortsExhausted |
• |
值名称:TcpMaxHalfOpen |
• |
值名称:TcpMaxHalfOpenRetried |
同时附上codeproject中的启用SYN泛洪攻击的代码C++实现。(可用A simple IOCP ServerClient Class查找源码)。
BOOL IOCPS::XPNTSYNFloodProtection(int iValue, int iTcpMaxHalfOpen, int iTcpMaxHalfOpenRetried,int iTcpMaxPortsExhausted,int iTcpMaxConnectResponseRetransmissions)
{
CString sKey_PATH="//SYSTEM//CurrentControlSet//Services//Tcpip//Parameters";
CString sKey_SynAttackProtect="SynAttackProtect";
CString sKey_TcpMaxHalfOpen="TcpMaxHalfOpen";
CString sKey_TcpMaxHalfOpenRetried="TcpMaxHalfOpenRetried";
CString sKey_TcpMaxPortsExhausted="TcpMaxPortsExhausted";
CString sKey_TcpMaxConnectResponseRetransmissions="TcpMaxConnectResponseRetransmissions";
HKEY hKey;
DWORD val=0;
LONG r=0;
BOOL bRet=TRUE;
//
// Set the sKey_SynAttackProtect
//
val=iValue;
if (RegOpenKey(HKEY_LOCAL_MACHINE, sKey_PATH, &hKey) != ERROR_SUCCESS)
if (RegCreateKey(HKEY_LOCAL_MACHINE, sKey_SynAttackProtect, &hKey) != ERROR_SUCCESS)
return FALSE;
r = RegSetValueEx(hKey, sKey_SynAttackProtect, 0, REG_DWORD, (BYTE *)&val, sizeof(val));
RegCloseKey(hKey);
bRet&= (r == ERROR_SUCCESS);
//
// Special Parameters is used.
//
if(iValue==1)
{
//
// Set the sKey_SynAttackProtect
//
val=iTcpMaxHalfOpenRetried;
if (RegOpenKey(HKEY_LOCAL_MACHINE, sKey_PATH, &hKey) != ERROR_SUCCESS)
if (RegCreateKey(HKEY_LOCAL_MACHINE, sKey_TcpMaxHalfOpen, &hKey) != ERROR_SUCCESS)
return FALSE;
r = RegSetValueEx(hKey, sKey_TcpMaxHalfOpen, 0, REG_DWORD, (BYTE *)&val, sizeof(val));
RegCloseKey(hKey);
bRet&= (r == ERROR_SUCCESS);
//
// Set the sKey_TcpMaxHalfOpenRetried
//
val=iTcpMaxHalfOpenRetried;
if (RegOpenKey(HKEY_LOCAL_MACHINE, sKey_PATH, &hKey) != ERROR_SUCCESS)
if (RegCreateKey(HKEY_LOCAL_MACHINE, sKey_TcpMaxHalfOpenRetried, &hKey) != ERROR_SUCCESS)
return FALSE;
r = RegSetValueEx(hKey, sKey_TcpMaxHalfOpenRetried, 0, REG_DWORD, (BYTE *)&val, sizeof(val));
RegCloseKey(hKey);
bRet&= (r == ERROR_SUCCESS);
//
// Set the sKey_TcpMaxPortsExhausted
//
val=iTcpMaxPortsExhausted;
if (RegOpenKey(HKEY_LOCAL_MACHINE, sKey_PATH, &hKey) != ERROR_SUCCESS)
if (RegCreateKey(HKEY_LOCAL_MACHINE, sKey_TcpMaxPortsExhausted, &hKey) != ERROR_SUCCESS)
return FALSE;
r = RegSetValueEx(hKey, sKey_TcpMaxPortsExhausted, 0, REG_DWORD, (BYTE *)&val, sizeof(val));
RegCloseKey(hKey);
bRet&= (r == ERROR_SUCCESS);
//
// Set sKey_TcpMaxConnectResponseRetransmissions
//
val=iTcpMaxConnectResponseRetransmissions;
if (RegOpenKey(HKEY_LOCAL_MACHINE, sKey_PATH, &hKey) != ERROR_SUCCESS)
if (RegCreateKey(HKEY_LOCAL_MACHINE, sKey_TcpMaxConnectResponseRetransmissions, &hKey) != ERROR_SUCCESS)
return FALSE;
r = RegSetValueEx(hKey, sKey_TcpMaxConnectResponseRetransmissions, 0, REG_DWORD, (BYTE *)&val, sizeof(val));
RegCloseKey(hKey);
bRet&= (r == ERROR_SUCCESS);
}
return bRet;
}