<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>StephenChan&#039;s Tech Space &#187; TCP/IP</title>
	<atom:link href="http://blog.endlesscode.com/category/tcp-ip/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.endlesscode.com</link>
	<description>Stay Hungry. Stay Foolish.</description>
	<lastBuildDate>Tue, 25 Oct 2011 01:15:07 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>zz SSH协议基础</title>
		<link>http://blog.endlesscode.com/2010/04/25/ssh-base/</link>
		<comments>http://blog.endlesscode.com/2010/04/25/ssh-base/#comments</comments>
		<pubDate>Sun, 25 Apr 2010 16:50:41 +0000</pubDate>
		<dc:creator>Stephen</dc:creator>
				<category><![CDATA[TCP/IP]]></category>

		<guid isPermaLink="false">http://blog.endlesscode.com/?p=647</guid>
		<description><![CDATA[SSH的英文全称为Secure Shell，是IETF（Internet Engineering Task Force）的Network Working Group所制定的一族协议，其目的是要在非安全网络上提供安全的远程登录和其他安全网络服务。 我们可以简单理解为：Rlogin和Telnet等的替代方案。SSH的使用场景如下图所示，具体请参考下文SSH的框架。 SSH 基本框架 SSH协议框架中最主要的部分是三个协议： 传输层协议 用户认证协议 连接协议 同时SSH协议框架中还为许多高层的网络安全应用协议提供扩展的支持。它们之间的层次关系可以用如下图来表示： 传输层协议（The Transport Layer Protocol）提供服务器认证，数据机密性，信息完整性 等的支持； 用户认证协议（The User Authentication Protocol） 则为服务器提供客户端的身份鉴别； 连接协议（The Connection Protocol） 将加密的信息隧道复用成若干个逻辑通道，提供给更高层的应用协议使用； 各种高层应用协议可以相对地独立于SSH基本体系之外，并依靠这个基本框架，通过连接协议使用SSH的安全机制。 SSH安全验证级别 第一种级别(基于口令的安全验证),只要你知道自己帐号和口令，就可以登录到远程主机。所有传输的数据都会被加密，但是不能保证你正在连接的服务器就是你想连接的服务器。可能会有别的服务器在冒充真正的服务器，也就是受到“中间人”这种方式的攻击。 第二种级别(基于密匙的安全验证)需要依靠密匙 先为自己创建一对密匙，并把公匙放在需要访问的服务器上； 客户端软件会向服务器发出请求，请求用你的密匙进行安全验证； 服务器收到请求之后，在该服务器目录下寻找公匙，然后把它和你发送过来的公匙进行比较。若两密匙一致，服务器就用公匙加密“质询”(challenge)并把它发送给客户端软件； 客户端软件收到“质询”之后就可以用 私密 解密再把它发送给服务器。 用这种方式，你必须知道自己密匙的口令。但是，与第一种级别相比，第二种级别不需要在网络上传送口令，它不仅加密所有传送的数据，而且“中间人”这种攻击方式也是不可能的(因为他没有你的私人密匙)。但是整个登录的过程可能需要10秒。 &#8230; <a href="http://blog.endlesscode.com/2010/04/25/ssh-base/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>SSH的英文全称为Secure Shell，是IETF（Internet Engineering Task Force）的Network Working Group所制定的一族协议，其目的是要在非安全网络上提供安全的远程登录和其他安全网络服务。 我们可以简单理解为：Rlogin和Telnet等的替代方案。SSH的使用场景如下图所示，具体请参考下文SSH的框架。</p>
<p><img class="aligncenter size-full wp-image-649" title="ssh_useage" src="http://blog.endlesscode.com/wp-content/uploads/2010/04/ssh_useage.gif" alt="ssh_useage" width="482" height="502" /></p>
<h3 id="SSH基本框架"><span id="more-647"></span>SSH 基本框架</h3>
<blockquote><p>SSH协议框架中最主要的部分是三个协议：</p></blockquote>
<ul>
<li>传输层协议</li>
<li>用户认证协议</li>
<li>连接协议<br />
同时SSH协议框架中还为许多高层的网络安全应用协议提供扩展的支持。它们之间的层次关系可以用如下图来表示：</li>
</ul>
<p><img class="aligncenter size-full wp-image-650" title="SSH_layer" src="http://blog.endlesscode.com/wp-content/uploads/2010/04/SSH_layer.gif" alt="SSH_layer" width="528" height="224" /></p>
<ul>
<li>传输层协议（The Transport Layer Protocol）提供服务器认证，数据机密性，信息完整性 等的支持；</li>
<li>用户认证协议（The User Authentication Protocol） 则为服务器提供客户端的身份鉴别；</li>
<li>连接协议（The Connection Protocol） 将加密的信息隧道复用成若干个逻辑通道，提供给更高层的应用协议使用； 各种高层应用协议可以相对地独立于SSH基本体系之外，并依靠这个基本框架，通过连接协议使用SSH的安全机制。</li>
</ul>
<h3 id="SSH安全验证级别">SSH安全验证级别</h3>
<ul>
<li>第一种级别(<strong>基于口令</strong>的安全验证),只要你知道自己帐号和口令，就可以登录到远程主机。所有传输的数据都会被加密，但是不能保证你正在连接的服务器就是你想连接的服务器。可能会有别的服务器在冒充真正的服务器，也就是受到“中间人”这种方式的攻击。</li>
<li>第二种级别(<strong>基于密匙</strong>的安全验证)需要依靠密匙
<ul>
<li>先为自己创建一对密匙，并把<strong>公匙</strong>放在需要访问的服务器上；</li>
<li>客户端软件会向服务器发出请求，请求用你的<strong>密匙</strong>进行安全验证；</li>
<li>服务器收到请求之后，在该服务器目录下寻找<strong>公匙</strong>，然后把它和你发送过来的<strong>公匙</strong>进行比较。若两密匙一致，服务器就用公匙加密“质询”(challenge)并把它发送给客户端软件；</li>
<li>客户端软件收到“质询”之后就可以用 私密 解密再把它发送给服务器。</li>
</ul>
</li>
</ul>
<p>用这种方式，你必须知道自己密匙的口令。但是，与第一种级别相比，第二种级别不需要在网络上传送口令，它不仅加密所有传送的数据，而且“中间人”这种攻击方式也是不可能的(因为他没有你的私人密匙)。但是整个登录的过程可能需要10秒。</p>
<h2 id="SSH的工作过程">SSH 的工作过程</h2>
<p>在整个通讯过程中，为实现 SSH的安全连接，服务器端与客户端要经历如下<strong>五个阶段</strong>：</p>
<ul>
<li><strong>版本号协商</strong>阶段，SSH目前包括 SSH1和SSH2两个版本， 双方通过版本协商确定使用的版本</li>
<li><strong>密钥和算法协商</strong>阶段，SSH支持多种加密算法， 双方根据本端和对端支持的算法，协商出最终使用的算法</li>
<li><strong>认证</strong>阶段，SSH客户端向服务器端发起认证请求， 服务器端对客户端进行认证</li>
<li><strong>会话请求</strong>阶段， 认证通过后，客户端向服务器端发送会话请求</li>
<li><strong>交互会话</strong>阶段 ，会话请求通过后，服务器端和客户端进行信息的交互</li>
</ul>
<h3 id="a1.版本号协商阶段">1 . 版本号协商阶段</h3>
<ol>
<li>服务器打开端口 22，等待客户端连接。</li>
<li>客户端向服务器端发起 TCP初始连接请求，TCP连接建立后，服务器向客户端发送第一个报文，包括版本标志字符串，格式为“SSH－&lt;主协议版本号&gt;.&lt;次 协议版本号&gt;－&lt;软件版本号&gt;”，协议版本号由主版本号和次版本号组成，软件版本号主要是为调试使用。</li>
<li>客户端收到报文后，解析该数据包，如果服务器端的协议版本号比自己的低，且客户端能支持服务器端的低版本，就使用服务器端的低版本协议号，否则使用自己的协议版本号。</li>
<li>客户端回应服务器一个报文，包含了客户端决定使用的协议版本号。服务器比较客户端发来的版本号，决定是否能同客户端一起工作。</li>
<li>如果协商成功，则进入密钥和算法协商阶段，否则服务器端断开 TCP连接。</li>
</ol>
<p>Note：              版本号协商阶段报文都是采用明文方式传输的。</p>
<h3 id="a2.密钥和算法协商阶段">2. 密钥和算法协商阶段</h3>
<ol>
<li>服务器端和客户端分别发送算法协商报文给对端，报文中包含自己支持的公钥算法列表、加密算法列表、MAC（Message Authentication Code，消息验证码）算法列表、压缩算法列表等;</li>
<li>服务器端和客户端根据对端和本端支持的算法列表得出最终使用的算法。</li>
<li>服务器端和客户端利用 DH交换（Diffie-Hellman Exchange）算法、主机密钥对等参数，生成会话密钥和会话 ID。通过以上步骤，服务器端和客户端就取得了相同的会话<strong>密钥</strong>和<strong>会话ID</strong>。
<ul>
<li>对于后续传输的数据，两端都会使用会话<strong>密钥</strong>进行<strong>加密和解密</strong>，保证了数据传送的安全</li>
<li>在认证阶段，两端会使用<strong>会话 ID</strong>用于<strong>认证过程</strong>。</li>
</ul>
</li>
</ol>
<p>Note：在协商阶段之前，服务器端已经生成 RSA或 DSA密钥对，他们主要用于参与会话密钥的生成。</p>
<h3 id="a3.认证阶段">3. 认证阶段</h3>
<ol>
<li>客户端向服务器端发送认证请求，认证请求中包含用户名、认证方法、与该认证方法相关的内容（如：password认证时，内容为密码）。</li>
<li>服务器端对客户端进行认证，如果认证失败，则向客户端发送认证失败消息，其中包含可以再次认证的方法列表。</li>
<li>客户端从认证方法列表中选取一种认证方法再次进行认证。</li>
<li>该过程反复进行， 直到认证成功或者认证次数达到上限， 服务器关闭连接为止。</li>
</ol>
<h4 id="SSH提供两种认证方式"><em>SSH提供两种认证方式：</em></h4>
<ol>
<li>password认证：客户端向服务器发出 password认证请求，将用户名和密码加密后发送给服务器；服务器将该信息解密后得到用户名和密码的明文，与设备上保存的用户名和密码进行比较，并返回认证成功或失败的消息。</li>
<li>publickey 认证：采用数字签名的方法来认证客户端。目前，设备上可以利用RSA和 DSA两种公共密钥算法实现数字签名。客户端发送包含用户名、公共密钥和公共密钥算法的 publickey 认证请求给服务器端。服务器对公钥进行合法性检查，如果不合法，则直接发送失败消息；否则，服务器利用数字签名对客户端进行认证，并返回认证成功或失败的 消息</li>
</ol>
<h4 id="SSH2.0还提供了password-publickey认证和any认证:"><em>SSH2.0还提供了 password-publickey 认证和 any 认证:</em></h4>
<ol>
<li>password-publickey 认证：指定该用户的认证方式为 password 和 publickey认证同时满足。客户端版本为 SSH1的用户只要通过其中一种认证即可登录；客户端版本为 SSH2的用户必须两种认证都通过才能登录。</li>
<li>any认证：指定该用户的认证方式可以是 password，也可以是 publickey。</li>
</ol>
<h3 id="a4.会话请求阶段">4.会话请求阶段</h3>
<ol>
<li>服务器等待客户端的请求；</li>
<li>认证通过后，客户端向服务器发送会话请求；</li>
<li>服务器处理客户端的请求。请求被成功处理后， 服务器会向客户端回应 SSH_SMSG_SUCCESS包，SSH进入交互会话阶段；否则回应 SSH_SMSG_FAILURE包，表示服务器处理请求失败或者不能识别请求。</li>
</ol>
<h3 id="a5.交互会话阶段">5.交互会话阶段</h3>
<p>在这个模式下，数据被双向传送：</p>
<ol>
<li>客户端将要执行的命令加密后传给服务器;</li>
<li>服务器接收到报文，解密后执行该命令,将执行的结果加密发还给客户端;</li>
<li>客户端将接收到的结果解密后显示到终端上.</li>
</ol>
<h3 id="a6.SSHQA">6.SSH Q &amp; A</h3>
<blockquote><p><strong>Q1</strong>: SSH的版本和区别。</p>
<p>SSH2避免了RSA的专利问题，并修补了CRC的缺陷。SSH2用数字签名算法（DSA）和Diffie-Hellman（DH）算法代替RSA来完成对称密钥的交换，用HMAC来代替CRC。同时SSH2增加了AES和Twofish等对称加密算法。</p>
<p><strong>A1</strong>: SSH(Secure SHell)到目前为止有两个不兼容的版本——SSH1和SSH2。SSH1又分为1.3和1.5两个版本。SSH1采用DES、3DES、 Blowfish和RC4等对称加密算法保护数据安全传输，而对称加密算法的密钥是通过非对称加密算法（RSA）来完成交换的。SSH1使用循环冗余校验 码（CRC）来保证数据的完整性，但是后来发现这种方法有缺陷。</p>
<p>更多内容请参考<a href="http://fengnet.com/book/VPNs%20Illustrated%20Tunnels%20%20VPNsand%20IPsec/ch07lev1sec2.html"><span>The SSHv1 Protocol</span></a> &amp; <a href="http://fengnet.com/book/VPNs%20Illustrated%20Tunnels%20%20VPNsand%20IPsec/ch07lev1sec3.html"><span>The SSHv2 Protocol</span></a></p>
<p><strong>Q2</strong>: 什么是HMAC？</p>
<p><strong>A2</strong>: HMAC(Hash Message Authentication Code) ，散列消息鉴别码，基于密钥的Hash算法的认证协议。消息鉴别码实现鉴别的原理是，用公开函数和密钥产生一个固定长度的值作为认证标识，用这个标识鉴别 消息的完整性。使用一个密钥生成一个固定大小的小数据块，即MAC，并将其加入到消息中，然后传输。接收方利用与发送方共享的密钥进行鉴别认证等。</p>
<p><strong>Q3</strong>: 什么是X11 forwarding？</p>
<p><strong>A3</strong>: sh的X11 forwarding特性可以使X client和X server安全地通讯。使用X11 forwarding后，从X client到X Server方向的数据先被送至ssh server，ssh server利用和ssh client的安全通道转发给ssh client，再由ssh client转发给X server，从X server到X client的数据流同理。这里ssh server和ssh client充当了X client和X server间数据的转发器，由于ssh server和X client、ssh client和X server一般在同一台机器上，它们之间是一种安全的进程间通讯，而ssh server和ssh client间的通讯也是安全的，所以X client和X server间的通讯就是安全的。</p>
<p><strong>Q4</strong>: 什么是TTY？</p>
<p><strong>A4</strong>: 终端是一种字符型设备，它有多种类型，通常使用tty来简称各种类型的终端设备。tty是 Teletype的缩写。Teletype是最早出现的一种终端设备，很象电传打字机，是由Teletype公司生产的。设备名放在特殊文件目录/dev/下。</p>
<p><strong>Q5</strong>: 简单描述下SSH运行的过程？</p>
<p><strong>A5</strong>:简要过程如下：</p>
<ul>
<li>Client端向Server端发起SSH连接请求。</li>
<li>Server端向Client端发起版本协商。</li>
<li>协商结束后Server端发送Host Key公钥 Server Key公钥，随机数等信息。到这里所有通信是不加密的。</li>
<li>Client端返回确认信息，同时附带用公钥加密过的一个随机数，用于双方计算Session Key。</li>
<li>进入认证阶段。从此以后所有通信均加密。</li>
<li>认证成功后，进入交互阶段。</li>
</ul>
</blockquote>
<h3>转载来源：http://blog.csdn.net/oncoding/archive/2009/07/20/4365062.aspx</h3>
]]></content:encoded>
			<wfw:commentRss>http://blog.endlesscode.com/2010/04/25/ssh-base/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>zz “西厢计划”原理小解</title>
		<link>http://blog.endlesscode.com/2010/03/21/west-chamber/</link>
		<comments>http://blog.endlesscode.com/2010/03/21/west-chamber/#comments</comments>
		<pubDate>Mon, 22 Mar 2010 05:27:01 +0000</pubDate>
		<dc:creator>Stephen</dc:creator>
				<category><![CDATA[TCP/IP]]></category>

		<guid isPermaLink="false">http://blog.endlesscode.com/?p=512</guid>
		<description><![CDATA[待月西厢下，迎风户半开。隔墙花影动，疑是玉人来。 最近推上最流行的一个关键词是”西厢计划”, 这个计划名字取得很浪漫，客户端叫做张生，对，就是西厢记里面那个翻墙去见崔莺莺小姐的张生；显然，服务器端必然叫做崔莺莺。客户端的张生是最重要的部 件，可以不依赖于服务端工作。因为西厢计划的作者只是简要的介绍了一下原理，其他报道又语焉不详，我当时就觉得很好奇，花了昨天一个晚上详细读了一下源代 码，终于知道怎么回事了，觉得原理非常漂亮，所以写篇文章介绍总结一下。 先说大方向。大家都知道，连接被重置的本质，是因为收到了破坏连接的一个 TCP Reset 包。以前剑桥大学有人实验过，客户端和服务器都忽略 Reset, 则通信可以不受影响。但是这个方法其实只有理论价值，因为绝大多数服务器都不可能忽略 Reset 的 (比如 Linux, 需要 root 权限配置iptables, 而且这本身也把正常的 Reset 给忽略了)。只要服务器不忽略 Reset, 客户端再怎么弄都没用，因为服务器会停止发送数据，Reset 这条连接。所以，很多报道说西厢计划是忽略 Reset, 我从源代码来看应该不是这样。在我看来，西厢计划是利用了墙的一个可能的弱点–墙只在连接发起的时候把一个 TCP 连接加入监听序列，如果墙认为这个连接终止了，就会从监听序列中去掉这条记录，这样，这条连接上后续的包就不会被监听。西厢计划就是让墙“认为”这个连接 终止的一个绝妙的方法。只要墙认为这个连接两端都是死老虎，墙就不会触发关键词检测，其后所有的数据，都不存在连接被重置的问题了。 如何让一个连接置之死地而后生，就是西厢计划那帮黑客神奇的地方了。这也不是一日之功。 首先，这帮牛人发现，墙的是一个入侵检测系统，把含有关键字的包当成一种“入侵”来对待。采取这种设计有很多好处，但缺点是入侵检测系统可能具有的问题， 墙都可能有。西厢计划主页上那篇著名的论文就是讲这些七七八八的漏洞的。可以说处理这些七七八八的漏洞是非常困难的，迫使墙的设计者“拆东墙，补西墙”。 这样补来补去，外表看起来好像很牛逼的墙，其实有很多本质上无法简单修补的漏洞，其中有一个致命的，就是 TCP 连接状态的判定问题。 出于入侵检测系统这种设计的局限，墙没有，也没办法准确判定一条 TCP 连接的状态，而只是根据两边收到的数据来“推测”连接的状态。而所有的关键词检测功能，都是基于“连接还活着”的这个推测的结果的。因为墙的规则是在连接 发起的时候开始对这条连接的检测，在连接终止的时候停止对这条连接的检测，所以，一旦对连接的状态推测错误，把还活着的连接当成已经关闭的连接，墙就会放 弃对这条连接上随后所有的包的检测，他们都会都透明的穿过墙的入侵检测。 &#8230; <a href="http://blog.endlesscode.com/2010/03/21/west-chamber/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<div>
<p>待月西厢下，迎风户半开。隔墙花影动，疑是玉人来。</p>
<p>最近推上最流行的一个关键词是”西厢计划”, 这个计划名字取得很浪漫，客户端叫做张生，对，就是西厢记里面那个翻墙去见崔莺莺小姐的张生；显然，服务器端必然叫做崔莺莺。客户端的张生是最重要的部 件，可以不依赖于服务端工作。因为西厢计划的作者只是简要的介绍了一下原理，其他报道又语焉不详，我当时就觉得很好奇，花了昨天一个晚上详细读了一下源代 码，终于知道怎么回事了，觉得原理非常漂亮，所以写篇文章介绍总结一下。</p>
<p>先说大方向。大家都知道，连接被重置的本质，是因为收到了破坏连接的一个 TCP Reset 包。以前剑桥大学有人实验过，客户端和服务器都忽略 Reset, 则通信可以不受影响。但是这个方法其实只有理论价值，因为绝大多数服务器都不可能忽略 Reset 的 (比如 Linux, 需要 root 权限配置iptables, 而且这本身也把正常的 Reset 给忽略了)。只要服务器不忽略 Reset, 客户端再怎么弄都没用，因为服务器会停止发送数据，Reset 这条连接。所以，很多报道说西厢计划是忽略 Reset, 我从源代码来看应该不是这样。在我看来，西厢计划是利用了墙的一个可能的弱点–墙只在连接发起的时候把一个 TCP 连接加入监听序列，如果墙认为这个连接终止了，就会从监听序列中去掉这条记录，这样，这条连接上后续的包就不会被监听。西厢计划就是让墙“认为”这个连接 终止的一个绝妙的方法。只要墙认为这个连接两端都是死老虎，墙就不会触发关键词检测，其后所有的数据，都不存在连接被重置的问题了。<span id="more-512"></span></p>
<p>如何让一个连接置之死地而后生，就是西厢计划那帮黑客神奇的地方了。这也不是一日之功。 首先，这帮牛人发现，墙的是一个入侵检测系统，把含有关键字的包当成一种“入侵”来对待。采取这种设计有很多好处，但缺点是入侵检测系统可能具有的问题， 墙都可能有。西厢计划主页上那篇著名的论文就是讲这些七七八八的漏洞的。可以说处理这些七七八八的漏洞是非常困难的，迫使墙的设计者“拆东墙，补西墙”。 这样补来补去，外表看起来好像很牛逼的墙，其实有很多本质上无法简单修补的漏洞，其中有一个致命的，就是 TCP 连接状态的判定问题。 出于入侵检测系统这种设计的局限，墙没有，也没办法准确判定一条 TCP 连接的状态，而只是根据两边收到的数据来“推测”连接的状态。而所有的关键词检测功能，都是基于“连接还活着”的这个推测的结果的。因为墙的规则是在连接 发起的时候开始对这条连接的检测，在连接终止的时候停止对这条连接的检测，所以，一旦对连接的状态推测错误，把还活着的连接当成已经关闭的连接，墙就会放 弃对这条连接上随后所有的包的检测，他们都会都透明的穿过墙的入侵检测。</p>
<p>上面只是想法，具体到 TCP 协议实现这一层，就要只迷惑墙，还不能触及我要通信的服务器。最理想的情况下，在任何有效通信之前，就能让墙出现错误判断，这些，就需要对 TCP 协议有深刻理解了。西厢计划的那帮黑客，居然真的去读 TCP 几百页的 RFC，还居然就发现了方法（这里我假设读者都知道 TCP 的三次握手过程和序列号每次加一的规则）。 我们都知道，三次握手的时候，在收到服务器的 SYN/ACK 的时候，客户端如果发送 ACK 并且序列号+1 就算建立连接了，但是客户端如果发送一个序列号没 +1 的 FIN （表示连接终止，但是服务器知道，这时候连接还没建立呢， FIN 这个包状态是错的，加上序列号也是错的，服务器自己一判断，就知道这个包是坏包，按照标准协议，服务器随手丢弃了这个包）, 但这个包，过墙的时候，在墙看来，是表示连接终止的(墙是 ma de in china, 是比较山寨的，不维护连接状态，并且，墙并没有记下刚才服务器出去的 SYN/ACK 的序列号，所以墙不知道序列号错了）。所以，墙很高兴的理解为连接终止，舒了一口气去重置其他连接了， 而这个连接，就成了僵尸，墙不管你客户端了，而这时候，好戏才刚刚开始。</p>
<p>事实上，墙是双向检测的（或者说对每个包都检测的），因此，对服务器和客户端实现相同的对待方法，所以，墙不管客户端还不行，假如服务端有关键词传 给客户端，墙还是有可能要发飙的（这里说有可能，因为我也不知道）。所以，最好的办法就是，让服务端也给墙一个终止连接的标志就好了。可是这个说起来简 单，做起来难，怎么能让不受自己控制的服务器发一个自己想要的包呢？ 西厢计划的那帮黑客，再次去读几百页的 RFC, 令人惊讶的发现，他们居然在 RFC 上发现了一个可以用的特性。我们上面说了，三次握手的时候，在收到 SYN/ACK 后，客户端要给服务器发送一个序列号+1 的ACK，可是，假如我不+1呢，直接发 ACK 包给服务器。 墙已经认为你客户端是死老虎了，不理你了，不知道你搞什么飞机，让这个 ACK 过了。可是服务器一看，不对啊，你给我的不是我期待的那个序列号， RFC 上说了，TCP 包如果序列号错了的话，就回复一个 Reset. 所以，服务器就回复了一个 Reset。这个 Reset 过墙的时候，墙一看乐了，服务器也终止连接了，好吧，两边都是死老虎了，我就不监听这条连接了。而至于客户端，这个服务器过来的 Reset 非常好识别，忽略就是。随后，客户端开始正确的发送 ACK, 至此，三次握手成功，真正的好戏开始，而墙则认为客户端和服务器都是死老虎，直接放过。所以，张生就这样透明的过了墙。 至于过墙以后所有的事情，《西厢记》里面都有记载，各位读者自行买书学习。</p>
<p>现在的西厢计划客户端，即“张生”模块的防连接重置的原理就是这样，服务器端，即莺莺模块的实现也是类似的。防DNS那个，不懂 DNS 协议，所以看不懂。我猜想，因为开发人员都是黑客，所以自然喜欢用最经得起折腾和高度定制的 Linux 开发。 现在看西厢计划的实现，因为依赖于 Linux 内核模块 netfilter, 在 Linux 上如鱼得水，但往其他平台的移植可能是个亟待解决的问题。 我觉得，在其他平台上，可以通过 libpcap 和 libnet ，在用户态实现相同的功能，就是有点麻烦而已，有兴趣的懂网络的可以照西厢计划原理，在家自行做出此功能；当然，全中国人民都用 Linux 最好 :)</p>
<p>PS 1: 据说是西厢计划一个作者画的原理图：http://img.ly/DIi<br />
PS 2: 我对 TCP 的理解仅限于课本，如果上面的对技术的理解有错，请大家指出。<br />
PS 3: 有些漏洞，可能是设计上本质缺陷，不是那么容易修复的。<br />
PS 4: 除了最后一个图，本文没有其他相关链接，如需相关资料，自行 Google。</p>
<p><img class="aligncenter size-full wp-image-513" title="large_zhang" src="http://blog.endlesscode.com/wp-content/uploads/2010/03/large_zhang.png" alt="large_zhang" width="550" height="413" /></p>
<h4>引用来源：http://blog.youxu.info/2010/03/14/west-chamber/</h4>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.endlesscode.com/2010/03/21/west-chamber/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

