﻿<?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>BlogJava-关注技术，关注生活-文章分类-信息安全技术</title><link>http://www.blogjava.net/errorfun/category/18246.html</link><description>任何事情只要开始去做，永远不会太迟。</description><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 04:02:24 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 04:02:24 GMT</pubDate><ttl>60</ttl><item><title>[转][经典]Kerberos的原理</title><link>http://www.blogjava.net/errorfun/articles/86563.html</link><dc:creator>errorfun</dc:creator><author>errorfun</author><pubDate>Sat, 09 Dec 2006 10:07:00 GMT</pubDate><guid>http://www.blogjava.net/errorfun/articles/86563.html</guid><wfw:comment>http://www.blogjava.net/errorfun/comments/86563.html</wfw:comment><comments>http://www.blogjava.net/errorfun/articles/86563.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/errorfun/comments/commentRss/86563.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/errorfun/services/trackbacks/86563.html</trackback:ping><description><![CDATA[
		<p>
				<font size="2">这是</font>
				<a href="http://web.mit.edu/">
						<font color="#002c99" size="2">MIT</font>
				</a>
				<font size="2">（Massachusetts Institute of Technology）为了帮助人们 理解<em><font color="#0000cc"> Kerberos </font></em>的原理而写的一篇对话集。里面有两个虚构的人物 ： <font color="#ff0000">Athena</font>和<font color="#0066ff"><font color="#0066ff">Euripides</font></font>，通过<font color="#ff0000">Athena</font>不断的构思和<font color="#0066ff">Euripides</font>不断的寻找其中的漏洞，使大家明白了<em><font color="#0000cc"> Kerberos </font></em>协议的原理。 <br /><font color="#ff0000">Athena</font>: 雅典娜，智慧与技艺 的女神。 <br /><font color="#0066ff">Euripides</font>:欧里庇得斯，希腊的悲剧诗人。 <br />译文如下 ： <br /><br /><strong>第一幕</strong><br />在一个小工作间里。<font color="#ff0000">Athena</font>和<font color="#0066ff">Euripides</font>正在相邻的终端上工作。 <br /><font color="#ff0000">Athena</font>: 嗨，这个分时操作系统实在太慢了。我根本无法工作，因为每个人 都登上去了。<br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 不要对我报 怨。我只是在这工作。 <br /><font color="#ff0000">Athena</font>: 你知道我们需要什么吗？我们需要给 每一个人一台工作站，这样大家就不会担心计算机的速度了。并且，我们需要一个网络把所有的计算机都联起 来。 <br /><font color="#0066ff">Euripides</font>: 好。那么我们差不多要一千台工作站？ <br /><font color="#ff0000">Athena</font>: 差不多吧。 <br /><font color="#0066ff">Euripides</font>: 你知道一 台普通的工作站的硬盘有多大吗？那里放不下所有的软件。 <br /><font color="#ff0000">Athena</font>: 我已经有主意了。我们可以把系统软件放到服务器上。当你登录到工作站的时候，工作站会通过网络与其中一 台服务器上的系统软件联系。这样的设置让一组工作站都使用同一份系统软件，并且利于系统软件的升級。只 需改动服务器就可以了。 <br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 好的。个人的文件怎到办呢？在分时操作系统上，我可以登录并从终端上取走我的文件。我能到工作站上取我 的文件吗？我要象PC用户一样把我的文件放到磁盘上去吗？我希望不。 <br /><font color="#ff0000">Athena</font>: 我想我们可以用其它机器来存文件。你可以到任何一台机器上登录去取你的 文件。<br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 打印怎么办呢？每 个工作站都要有自已的打印机吗？谁来付钱？电子邮件呢？你怎么把邮件送到所有的工作站上去呢？ <br /><font color="#ff0000">Athena</font>: 啊……很明显我们没钱为每个人配一台打印机，但我们有专门的机 器做打印服务。你把请求送到服务器，它就为你打印。邮件也可以这样做。专门有一台邮件服务器。你如果想 要你的邮件，就联系邮件服务器，取走你的邮件。 <br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 你的工作站系统听起来很不错。如果我有一台，你知道我要做什 么吗？我要找出你的用户名，让我的工作站认为我就是你。然后我就去邮件服务器取走你的邮件。我会联上你 的文件服务器，移走你的文件，然后…… <br /><font color="#ff0000">Athena</font>: 你能做得到吗？ <br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 当然！这些网络服务器怎 么会知道我不是你？<br /><font color="#ff0000">Athena</font>: 嗯，我不知道。我想我需要认真思考一下 。<br /><font color="#0066ff">Euripides</font>: 好吧。你想出来后告诉我。<br /><br /><strong>第二 幕 </strong><br /><font color="#0066ff">Euripides</font>的办公室，第二天早上。<br /><font color="#0066ff">Euripides</font>坐在他的桌子旁边，读着他的邮件。<font color="#ff0000">Athena</font>来敲门. <br /><font color="#ff0000">Athena</font>: 我已经想出怎样保 护一个开放的网络系统，使象你那样不道德的人不能用别人的名字使用网络服务。 <br /><font color="#0066ff">Euripides</font>: 真的吗？坐吧。 <br />她坐下了。 <br /><font color="#ff0000">Athena</font>: 在我开始描述之前，我可以为我们的讨论先做一个约定吗？ <br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 什么约定？ <br /><font color="#ff0000">Athena</font>: 好，假设我这样说：“我想要我的邮件，于是我与邮件服务器联系，请求它 把邮件送到我的工作站上来。”实际上我并没有联系服务器。我用一个程序来与服务器联系并取得我的邮件， 这个程序就是这个服务的客户端。但我不想每次与服务器交互的时侯说“客户端怎样怎样”。.我只想说“我怎 样怎样”记住，客户端在代表我做所有的事。这样可以吗？ <br /><font color="#0066ff">Euripides</font>: 当然。没问题。<br /><font color="#ff0000">Athena</font>: 好。那 么我要开始阐述我所解决的问题了。在一个开放的网络环境中，提供服务的机器必须能够识别请求服务的实体 的身份。如果我去邮件服务器申请我的邮件，服务程序必须能够验证我就是我所申明的那个人。 <br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 没错。<br /><font color="#ff0000">Athena</font>: 你可以用一个笨办法解决这个问题：服务器让你输入你的口令。通过输口令 的办法我可以证明我是谁。 <br /><font color="#0066ff">Euripides</font>: 那确实很笨拙。在像那样的系 统里面，每一个服务器必须知道你的口令。如果网络有一千个用户,那每个服务器就要知道一千个口令。如果你 想改变口令，你就必须联系所有服务器，通知它们修改口令。我想你的系统不会那么笨。 <br /><font color="#ff0000">Athena</font>: 我的系统没那么笨。它是象这样工作的：不光人有口令，服务也有口令。每 个用户知道他们自已的口令，每个服务也知道它自已的口令。有一个认证服务知道所有的口令，用户的和服务 的。认证服务把口令保存在一个单独的中央数据库中。 <br /><font color="#0066ff">Euripides</font>: 这 个认证服务有一个名字吗？ <br /><font color="#ff0000">Athena</font>: 我还没想好。你想一个吧？ <br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 把死人送过冥河的人是谁？ <br /><font color="#ff0000">Athena</font>: <font color="#0000cc"><em>Charon </em></font><font color="#000000">？</font><br /><font color="#0066ff">Euripides</font>: 对，就是他。如果他不能证实 你的身份的话，他就不会把你送过河。 <br /><font color="#ff0000">Athena</font>: 你瞎编，是不是想重 写希腊神话。<em><font color="#0000cc"><em><font color="#0000cc"> Charon </font></em></font></em>不关心你的身份，他只是确定你死了没有。 <br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 你有更好的名字吗？ <br />停了一下。 <br /><font color="#ff0000">Athena</font>: 没有，真的没有。 <br /><font color="#0066ff">Euripides</font>: 好 ，那我们就把这个认证服务“<em><font color="#0000cc"><em><font color="#0000cc"> Charon </font></em></font></em>”。 <br /><font color="#ff0000">Athena</font>: 好，我猜我该描述一下这个 系统了吧，嗯？<br />比如说我们想要一种服务：邮件。在我的系统里面你无法使用一种服务，除非<em><font color="#0000cc"> Charon </font></em>告诉服务你确实是你所申明的人。也就是说你必须得到<em><font color="#0000cc"> Charon </font></em>的认证才能使用服务。当你向<em><font color="#0000cc"><em><font color="#0000cc"> Charon </font></em></font></em>请求认证的时候，你必须告诉<em><font color="#0000cc"><em><font color="#0000cc"> Charon </font></em></font></em>你要使用哪一个服务。如 果你想用邮件，你要告诉<em><font color="#0000cc"><em><font color="#0000cc"> Charon </font></em></font></em>。<em><font color="#0000cc"> Charon </font></em>请你证明你的身份。于是你 送给它你的密码。<em><font color="#0000cc"> Charon </font></em>把你的密码和它数据库中的密码相比较 。如果相等，<em><font color="#0000cc"> Charon </font></em>就认为你通过了验证。<em><font color="#0000cc"><em><font color="#0000cc"> Charon </font></em></font></em>现在就要让邮件服务知道 你通过了验证。既然<em><font color="#0000cc"><em><font color="#0000cc"> Charon </font></em></font></em>知道所有服务的密码，它也知道邮件服务的密码。<em><font color="#0000cc"><em><font color="#0000cc"> Charon </font></em></font></em>把邮件服务的密码给你， 你就可以使用这个密码使邮件服务相信你已通过验证。问题是，<em><font color="#0000cc"> Charon </font></em>不能直接给你密码，因为你会知道它。下次你想要邮件服务的时候，你就会绕过<em><font color="#0000cc"> Charon </font></em>使用邮件服务而不需要认证。你也可以假装某人来使用邮件服务。所 以不是直接给你邮件服务的密码，<em><font color="#0000cc"><em><font color="#0000cc"> Charon </font></em></font></em>给你一张邮件服务的“票”。这张票含有你的名字，并且名字是用邮件服务的密码 加密的。拿到票，你就可以向邮件服务请求你的邮件。你向邮件服务提出请求，并用 你的票来证明你的身份。 服务用它自已的密码来把票解密，如果票能被正确的解密，服务器将票里的用户名取出。服务把这个名字和随 票一起送上的用户名进行比较。如果相符，服务器就认为你通过了验证，就把你的邮件发给你。你认为怎么样 ？ <br /><font color="#0066ff">Euripides</font>: 我有些问题。 <br /><font color="#ff0000">Athena</font>: 我猜到了。请讲。 <br /><font color="#0066ff">Euripides</font>: 当 服务解密一张票的时候，它如何知道它是被正确的解密的？ <br /><font color="#ff0000">Athena</font>: 我不知道。 <br /><font color="#0066ff">Euripides</font>: 也许你应该在票里包含有服务的名字。这样当 服务解密票的时候，它就可以通过能否在票中找到自已的名字来判断解密是否正确。 <br /><font color="#ff0000">Athena</font>: 很好。那票就应该是这个样子： <br />(她把下面的东西写在了一张纸上) <br /><font color="#660066">票-{用户名：服务名}</font><br /><font color="#0066ff">Euripides</font>: 那票就只包含用户名和服务名？ <br /><font color="#ff0000">Athena</font>: 用服务的口令加密。 <br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 我不认为这些信息就可以让票安全。 <br /><font color="#ff0000">Athena</font>: 什么意思？ <br /><font color="#0066ff">Euripides</font>: 假设你向 <em><font color="#0000cc">Charon </font></em>请求一张邮件服务的票。<em><font color="#0000cc"><em><font color="#0000cc"> Charon </font></em></font></em>准备了一张有你名字 “<em><strong>tina</strong></em>”的票。假设在当票从<em><font color="#0000cc"> Charon </font></em>传给你的过程中我拷了一份。假设我让我的工作站相信我的用户名是 “<strong><em>tina</em></strong>”。邮件客户程序认为我就是你。用你的名字邮件客户程序用偷来的票向 邮件服务器提出请求。邮件服务器把票解密，认为它是合法的。票里的用户名和发送该票的用户名是匹配的。 邮件服务器就会发给我你的邮件。 <br /><font color="#ff0000">Athena</font>: 喔！那可不太好。 <br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 但是我想到了一个办法来解决 这个问题。或者说部分解决。我想<em><font color="#0000cc"> Charon </font></em>应该在票中包含更多的 信息。除了用户名，票还应包含请求票的用户的IP地址。这将给你增加一层安全性。我来演示。假设现在我偷 了你的票。这票有你工作站的IP地址，并且这地址配不上我的工作站的地址。用你的名字我把偷来的票送给邮 件服务器。服务程序把用户名和网络地址从票中解出，并试图匹配用户名和网络地址。用户名匹配可网络地址 不匹配。服务器拒绝了这张票，因为它明显是偷来的。 <br /><font color="#ff0000">Athena</font>: 英雄 ，英雄！我怎么会没想到。 <br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 好了，这就是我要表述的。 <br /><font color="#ff0000">Athena</font>: 那么票应该是这个样子的。 <br />她把下面的东西写在了黑板上。 <br /></font>
				<font size="2">
						<font color="#660066">票-{用户名：地址：服务名} <br /></font>
						<font color="#ff0000">Athena</font>: 现在我真的很激动。让我们来建一个<em><font color="#0000cc"><em><font color="#0000cc"> Charon </font></em></font></em>系统看看它是否工作！<br /><font color="#0066ff">Euripides</font>: 没那么快。对于你的系统我还有些问题。 <br /><font color="#ff0000">Athena</font>: 好吧。(<font color="#ff0000">Athena</font>从她的椅子上探出了身子) 快说。 <br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 听起来好像每次 我想要得到服务我都要去取一张新票。如果我整天的工作，我可能不只一次的要取我的邮件。我每次取邮件都 要去取一张新票吗？如果真是这样，我不喜欢你的系统。 <br /><font color="#ff0000">Athena</font>: 啊 。。。我不明白为什么票不能被重用。如果我已经得到了一张邮件服务的票，我可以一次又一次使用它。当邮 件客户程序用你的名字请求了服务，它就传了一份票的拷贝给服务。 <br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 好一些。但我仍有问题。你似乎暗示我每次使用还没有票的服务 时，我都必须给<em><font color="#0000cc"> Charon </font></em>我的密码我登录后想取我的文件。我向 <em><font color="#0000cc">Charon </font></em>请求我的票，这意味着我不得不使用我的密码。然后我想 读我的邮件。又向<em><font color="#0000cc"> Charon </font></em>发一次请求，我又要输一次我的密码。 现在假设我想把我的邮件送去打印。我又要向<em><font color="#0000cc"> Charon </font></em>发一次请求 。你知道了吧？ <br /><font color="#ff0000">Athena</font>: 啊，是的，我明白了。 <br /><font color="#0066ff">Euripides</font>: 并且如果这还不够糟的话，想想看：它好像是这样，当每次你要向 <em><font color="#0000cc">Charon </font></em>认证的时候，你就要用明文在网络上传输你的口令。像你 这样的聪明人可以监视网络并且得到别人的口令。如果我得到你的口令，我就可以用你的名字来使用任何服务 。 <br /><font color="#ff0000">Athena</font>叹了口气。 <br /><font color="#ff0000">Athena</font>: 确实有严重的问题。我想我该回设计室去了。 <br /><br /></font>
				<font size="2">
						<strong>第三幕 <br /></strong>第二天一早， <font color="#ff0000">Athena</font>在咖啡间遇上了<font color="#0066ff">Euripides</font>。在<font color="#0066ff">Euripides</font>倒咖啡的时候，<font color="#ff0000">Athena</font>拍了拍 <font color="#0066ff">Euripides</font><font color="#000000">。</font><br /><font color="#ff0000">Athena</font>: 我有了一个新的 <em><font color="#0000cc">Charon </font></em>的版 本来解决我们的问题。 <br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 真的吗？好快呀。<br /><font color="#ff0000">Athena</font>: 好，你看，这些问题困扰了我一夜。 <br /><font color="#0066ff">Euripides</font>: 一定是你良心发现了。我们去那边的小会议室吧？ <br /><font color="#ff0000">Athena</font>: 好的。 <br />两人去了小会议室。 <br /><font color="#ff0000">Athena</font>: 我要重新描述问题，但我要根据我们的需要进行适当的转换。 <br /><font color="#ff0000">Athena</font>清了清嗓子。 <br /><font color="#ff0000">Athena</font>: 第一个限制： 用户只输一次口令，在他们工作站启动的时候，这意味着当你需要申请新的服务的票时，不需输入你的口令。 第二个限制：口令不能在网络上进行明文传输。 <br /><font color="#0066ff">Euripides</font>: 好的。 <br /><font color="#ff0000">Athena</font>: 我以第一项限制开始：你只需要输入你的口令一次。我创造了 一个新的网络服务来解决这个问题。它叫做“票据授权”服务，这个服务把<em><font color="#0000cc"> Charon </font></em>的票给用户。使用它必须要有票：票据授权的票。票据授权服务其实只是<em><font color="#0000cc"> Charon </font></em>的一个版本，它可以存取<em><font color="#0000cc"> Charon </font></em>的数据库。它是<em><font color="#0000cc"> Charon </font></em>的一部分，可以让你通过票 而不是口令来进行认证。总之，认证系统现在是象这样工作的：你登录到一个工作站， 用一个叫 <em><b>kinit</b></em>的程序与<em><font color="#0000cc"> Charon </font></em>服务器通讯。你向 <em><font color="#0000cc">Charon </font></em>证明你的身份，<em><b>kinit</b></em>程序取得一张票据 授权票。现在你想从邮件服务器上取你的邮件。你还没有邮件服务器的票，所以你用“票据授权”票去取邮件 服务的票。你不需要使用口令去取新的服务票。 <br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 每次我想要另一种网络服务的时候，我都要去取一张“票据授权 ”票吗？ <br /><font color="#ff0000">Athena</font>: 不。记住，上次我们已经同意票是能被重用的。一 旦你要用到票据授权票，直接用就可以了。 <br /><font color="#0066ff">Euripides</font>: 好，有道理。 既然你能重用票，一旦你得到了某个服务的票，你就无需再去取了。 <br /><font color="#ff0000">Athena</font>: 对啊，那不好吗？ <br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 好的，我没话说，只要你在取得票据授权票的时候没有用明文在 网上传输你的口令。 <br /><font color="#ff0000">Athena</font>: 如我所说，我已解决了这个问题。听起 来好像是，当我说我要和<em><font color="#0000cc"> Charon </font></em>联系取得票据授权票的时候，你 就要在网络上传输明文密码。但其实不是这样的。实际上是，当你用<em><b>kinit</b></em>程序取得票据授权 票的时候，<em><b>kinit</b></em>没有把你的口令送给<em><font color="#0000cc"> Charon </font></em>服 务器，<em><b>kinit</b></em>只送你的用户名。 <br /><font color="#0066ff">Euripides</font>: 很好。 <br /><font color="#ff0000">Athena</font>: <em><font color="#0000cc">Charon </font></em>用用户名 去查找你的口令。然后<em><font color="#0000cc"> Charon </font></em>就会组一个包含票据授权票的包。 在送给你之前，<em><font color="#0000cc"> Charon </font></em>用你的口令去把这个包加密。你的工作站 收到了包。你输入你的口令。<em><b>kinit</b></em>用你的口令对这个包进行解密。如果成功你就向 <em><font color="#0000cc">Charon </font></em>成功的进行了认证。你现在有了票据授权票，你可以用这 张票来取得其它的票。这些奇思妙想怎么样？ <br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 我不知道……我正在思考。你知道你的系统一部分工作得很好。 你的系统只需要我认证一次。以后，<em><font color="#0000cc"> Charon </font></em>会给我服务的票而我 不需要关心。天衣无缝，天衣无缝。但服务票的设计还是有一些困扰我。服务票是可重用的。我同意它们应该 能被重用，但重用的服务票，由于它们自身的性质，是非常危险的。 <br /><font color="#ff0000">Athena</font>: 什么意思？ <br /><font color="#0066ff">Euripides</font>: 这样看。 假设你正在用一个不安全的工作站。在你登入后，你需要邮件服务票，打印票，和文件服务票。假设你无意中 在你退出后留下了那些票。现在假设我登录到那个工作站并且发现了那些票。我想制造一些麻烦，于是我就用 你的名字登录了。既然那些票上是你的名字，那我就可以取你的邮件，打大量的文件。这些完全是因为这些票 被偶然的放在了那里。并且我还可以把这些票拷走，永远的使用它们。 <br /><font color="#ff0000">Athena</font>: 但是这很好解决。我们可以写一个程序，在用户退出的时候把票销毁掉，这 些票也主不能再用了。 <br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 那么很明显你的系统应该有一个票据销毁程序，让用户依赖这样的机制是非常愚蠢的。你不能指望用户在他们 退出的时候会销毁票据。并且甚至不能依赖销毁票据本身，看下面的情况。我有一个程序可以监视网络并且拷 内别人的服务票据。假设我想牺牲你。我等你登到工作站的时候，打开我的程序并拷贝一份你的票。我等你退 出并离开。我把我的工作站的地址调整为你登录时用的地址。我让工作站认为我是你。我有你的票，你的用户 名，你的地址。我可以用这些票来使用你的服务。你离开工作站时销毁你的票已没并系。这些我偷来的票可以 一直使用下去，因为你现在的票并没有可以使用多少次的期限，或可以使用多长的时间。 <br /><font color="#ff0000">Athena</font>: 哦，我明白你所说的了！票不能是永远合法的，因为它可能是一个非常大的 安全隐患。我们应该限制每一张票可以用多长的时间，也许可以给每张票设一个有效期。 <br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 非常正确。我想票需要增加两项信息： 生存期表示票多长时间内是合法的，和一个时间标记来说明<em><font color="#0000cc"> Charon </font></em>是什么时候发出这张票的 。 <br />　<font color="#0066ff"><font color="#0066ff">Euripides</font></font>走到了黑板写下了如下的内容： <br />　　<font color="#660066">票｛用户名：地址：服务名：有效期：时间戳｝</font><br /><font color="#0066ff">Euripides</font>: 现在当服务解开票时，它检查票的用户名，地址是否与发送者匹配，然 后它用有效期和时间戳来检查票是否有效。 <br /><font color="#ff0000">Athena</font>: 很好。典型的票使用多长的有效期呢？ <br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 我不知道。也许是一个典型工作站的工作周期。就八小时吧。 <br /><font color="#ff0000">Athena</font>: 那如果我在工作站呆的时间超过八小时，所有的票将会失效。包括票据授权票。那我就要重新向<em><font color="#0000cc"> Charon </font></em>作认证，在八小时以后。 <br /><font color="#0066ff">Euripides</font>: 是不是不合理？ <br /><font color="#ff0000">Athena</font>: 我想 不是。好我们就定下来吧——票在八小时后失效。现在我有一个问题问你。假设我从网络上拷了你的票…… <br /><font color="#0066ff">Euripides</font>: (眨了眨眼睛）啊，天哪！你不会真的这样做吧？ <br /><font color="#ff0000">Athena</font>: 这只是为了讨论。我拷了你的票。现在我等你退出并离开。假设你 有一个医生的约会或聚会要参加，你在两个小时后退出，并且你在退出之前销毁了你的票。但我已经偷了你的 票，它们还可以使用六小时。这给了我足够的时间用你的名义去取你的文件并打印一千份什么东西。你看，时 间戳工作的很好如果小偷选择在它失效以后来用的话。如果小偷能在它失效之前用……。啊，好...当然，你是 对的。 <br /><font color="#ff0000">Athena</font>: 我想我们遇上了一个大问题了。(她叹了口气) <br />停了一下。 <br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 我想这意味着你今晚要忙了。再来点咖啡？ <br /><font color="#ff0000">Athena</font>: 为什么不。 <br /><br /><strong>第四幕</strong><br />第二天早上在 <font color="#0066ff">Euripides</font>的办公室。 <font color="#ff0000">Athena</font>来敲门。 <br /><font color="#0066ff">Euripides</font>: 你今早有黑眼圈了。 <br /><font color="#ff0000">Athena</font>: 好了，你知道的。又是一个漫漫长夜。 <br /><font color="#0066ff">Euripides</font>: 你解决了重演的问题了吗？ <br /><font color="#ff0000">Athena</font>: 我想是的。 <br /><font color="#0066ff">Euripides</font>: 请坐。 <br />她坐下了。 <br /><font color="#ff0000">Athena</font>: 照旧，我重申一下问题。票是可重用的，在一个限定的时间内（八小时）。如果谁偷了你的票并在它失效之前使用，我们毫无办法。 <br /><font color="#0066ff">Euripides</font>: 确实如此。 <br /><font color="#ff0000">Athena</font>: 我们可以 把这个问题理解为设计一种别人无法重用的票。 <br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 但这样的话你每次用新服务时都要取一张新票。 <br /><font color="#ff0000">Athena</font>: 对。但那是很笨的解决办法。（稍顿）啊，我怎样继续我的讨论呢？（她沉 思了一会儿）。好的，我要重述一个问题，看有什么必须条件。网络服务必须能够证明使用票的人就是票上所 申明的人。我来顺着认证的过程再走一遍，这样我就可以演示我的解决方案。我现在想用一个网络服务。我通 过启动工作站上的客户端来使用它。客户端送三样东西给服务器：我的名字，我的工作站的网络地址，适当的 服务票据。这张票包含了申请这张票的人的名字和他（她）申请时所使用的工作站的地址。它也包含了票的有 效期和时间戳。所有这些信息都被服务的密码加密了。 <br />我们现在的认证模式基于以下的测试：<br /><br /></font>
				<font size="2">
						<font color="#666666">
								<u>
										<font color="#cc6633">服务能对票解密吗？ <br />票在有效期以内吗 ？ <br />票中的名字和地址与申请者的名字和地址匹配吗？ <br />这些测试证明了什么？</font>
								</u>
								<br />
								<br />
						</font>第一个测试证明了票是不是来自<em><font color="#0000cc"> Charon </font></em>。如果票 不能被适当的解密，说明票不是来自真正的<em><font color="#0000cc"> Charon </font></em>。 真正的 <em><font color="#0000cc">Charon </font></em>会用服务的密码来加密票。<em><font color="#0000cc"> Charon </font></em>和服务是唯一知道服务密码的两个实体。如果票被成功的解密， 服务知道它来自于真的 <em><font color="#0000cc">Charon </font></em>.这个测试防止了有人伪造假票。第二项测试检查票是否在 有效期以内。如果过期，服务拒绝。这项测试阻止使用旧票，因为票可能是偷来的。第三项测试检查票的用户 名和地址是否匹配请求者的用户名和地址。如果测试失败，说明使用者使用了别人的票。这张票当然被拒绝。 如果名字和地址匹配，这个测试证明了什么？什么也没有。票可以被偷走，用户名和网络地址都可以被改变， 如果需要的话。正如我昨天指出的那样，票可以在有效期内被盗用。因为服务不能确定票的发送者是不是合法 用户。服务之所以无法判断是因为它没有与用户共享一个秘密。这样看。假如我正在埃尔斯诺尔（哈姆雷特中 的城堡）值勤，你打算来和我换班。但除非你说出正确的口令，否则我不会与你换班的。我们共享了一个秘密 。它可能是某人为所有值勤的人所设的。于是昨晚我就在想，为什么<em><font color="#0000cc"> Charon </font></em>不能为合法用户与服务之间设一个口令呢？<em><font color="#0000cc"> Charon </font></em>发一份口令给服务，同时发一份给用户。当服务从用户那里收到一张票，它可以用这个口令检验用户的合法性 。 <br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 等一下。<em><font color="#0000cc"> Charon </font></em>如何同时发两份口令？ <br /><font color="#ff0000">Athena</font>: 票据的拥用者从<em><font color="#0000cc"> Charon </font></em>的回应 中得到口令，像这个样子： <br />她在黑板上写下了： <br /><em><font color="#0000cc">Charon </font></em>的回应－[口令｜票] <br />服务从票中获取口令。票的格式如下： <br /><font color="#660066">票－｛口令：用户名：地址：服务名：有效期：时间戳｝</font><br />当你要请求服务时 ，客户端程序生成一个“验证器”。验证器包含了你的名字和你工作站的地址。客户端用口令把这些信息加密 ，口令是你请求票据时得到的。 <br />　<font color="#660066">验证器－｛用户名：地址｝</font>用口令 加密。 <br />生成验证器以后，客户端把它和票一起送给服务。因为服务没有口令，所以它不能解密验证器。 口令在票中，于是服务先解开票。解开票以后，服务得到以下的东西： <br /><br /></font>
				<font size="2">
						<u>
								<font color="#cc6600">票的有效期和时间戳； <br />票的拥有者的名字； <br />票拥有者的网络地址；<br />口 令。</font>
						</u>
						<br />
						<br />服务检查票是否过期。如果一切正常，服务就用口令去解验证器。如果解密没有 问题，服务将会得到一个用户名和网络地址。服务用它们去和票里的用户名和网络地址去匹配，如果正确，那 么服务认为票的发送者确实是票的真实拥有者。 <br /><font color="#ff0000">Athena</font>暂停了一下， 清了清喉咙，喝了点咖啡。 <br />我认为口令验证器的机制解决了盗用的问题。 <br /><font color="#0066ff">Euripides</font>: 也许。但我想。。。攻击这个系统我必须有验证器。 <br /><font color="#ff0000">Athena</font>: 不。你必须同时拥有验证器和票。没有票，验证器是没有用的。解开验证器 必须要有口令，服务必须解开票才会有口令。 <br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 好，我明白了，你是说当客户程序联系服务时，它同时送上票和 验证器？ <br /><font color="#ff0000">Athena</font>: 是的，我就是这个意思。 <br /><font color="#0066ff">Euripides</font>: 如是真是这样，什么可以阻止我把票和验证器都偷走呢？我可以写一个 程序，如果我拥有了票和验证器，我就可以一直使用它至有效期结束。我只需改变我的用户名和工作站的地址 。不是吗？</font>
				<font color="#ff0000">
						<br />
						<font size="2">Athena</font>
				</font>
				<font size="2">: (咬了咬她的嘴唇）是的。多沮丧啊。 <br /><font color="#0066ff">Euripides</font>: 等等，等等，等等！这不难解决。票在有效期内是可重用的， 但那并不意味着验证器是可重用的。假设我们设计了验证器只可以被用一次。这可以吗？ <br /><font color="#ff0000">Athena</font>: 好，也许。我样来想一下，客户端程序生成验证器，然后把它和票一起送给 服务。真的票和验证器比你拷贝的要先到。如果验证器只能被用一次，你的拷贝就失效了。啊，这就对了。我 们现在需要做的就是发明一和方法使得验证器只能被用一次。 <br /><font color="#0066ff">Euripides</font>: 没问题。我们把有效期和时间戳放在上面。假设每个验证有两分钟的有 效期。当你想用一个服务时客户端生成验证器，标上当前的时间，把它和票一起送给服务。服务器收到了票和 验证器，服务器解开验证器，它检查验证器的时间戳和有效期。如果验证器还没失效，所有其它的检查都通过 了，那么服务器就认为你通过了认证。假设我通过网络拷贝了一份验证器和票，我必须改变我的工作站的网络 地址和我的用户名，这差不多要用几分钟。那是非常苛刻的要求，我不认为是可能的，除非……嗯，有一个潜在的问题。假设不是在网络的转输中拷贝到票和验证器，我拷贝了一份原始的从<em><font color="#0000cc"> Charon </font></em>而来的包，这个包是你向<em><font color="#0000cc"> Charon </font></em>请求时的回应。这个包，有两个口令在里面：一个是你的，一个是服务的。服务的口令隐藏在票中，我取不到，但另一个 呢？那个你用来生成验证器的？ 如果我得到了口令，我就用它来建自已的验证器，如果我能建自已的验证器，我就能攻破你的系统。 <br /><font color="#ff0000">Athena</font>: 这就是我昨晚所想的，但是当我顺着票的处理过程一想，发现那样偷走验证器是不可能的。你在一台工作站坐下，用<em><b>kinit</b></em>程序得到你的票据授权票。<em><b>kinit</b></em>要求输入用户名，你输入以后，<em><b>kinit</b></em>把它送给 <em><font color="#0000cc">Charon </font></em>。<em><font color="#0000cc">Charon </font></em>用你的名字查找你的口令，然后生成一张票据授权票。作为处理的一部分，<em><font color="#0000cc"> Charon </font></em>生成了一个你与票据授权服务共享的口令。<em><font color="#0000cc">Charon </font></em>把口令和票据授权票一起送给你，并且在发送之前用你的口令将它加密。<em><font color="#0000cc">Charon </font></em>送出了包。某人取得了这个包，但他们无能为力，因为它是用你的口令加过密的。特别是，无人 可以偷走票据授权服务的口令。<em><b>kinit</b></em>收到了票据包并要求你输入你的口令。如果你输入正确的口令，<em><b>kinit</b></em>解开包取出了口令。现在你注意<em><b>kinit</b></em>的处理，你去取你的 邮件。你打开邮件客户端。这个程序查找一张邮件服务的票但没有找到（你还没取过你的邮件）。客户端用票据授权票去申请一张邮件服务的票。客户端为票据授权的过程生成了一个验证器，并用票据授权的口令把验证器加密。客户端把验证器送给了<em><font color="#0000cc"> Charon </font></em>，票据授权票，你的名字 ，你的工作站的地址，邮件服务的名字。票据授权服务收到了这些东西，并通过了认证检查。如果一切都通过 ，票据授权服务将会得到那个与你共享的口令。现在票据授权服务为你生成了一张邮件服务的票，在这个过程 中生成了一个你与邮件服务共享的口令。票据授权服务把这些东西打成包送给你的工作站。包里有票和口令。 在送包之前，票据授权服务用票据授权的口令把包加密。做完以后，包被送出去。这样邮件服务票的包通过网 络被送了出来。假设网络上的某人将它复制了一份。他不幸的发现包是用票据认证的口令加过密的。既然无法解密，他就不能得到邮件口令。没有口令，他就不能使用任何在网络上传送的邮件服务的票。现在我觉得我们是安全的。你认为呢？ <br /><font color="#0066ff">Euripides</font>: 也许吧。 <br /><font color="#ff0000">Athena</font>: 也许！你就只会说这个吗！ <br /><font color="#0066ff">Euripides</font>:（大笑）别在意。你现在应该知道我处理问题的方式了。我猜我和你昨晚都工作到了半夜。 <font color="#ff0000">Athena</font>: 哼！ <br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 好的，大半夜。实际上，这个系统似乎是完全可行的。口令的方案解决了我昨晚想到的一个问题：相互验证的问题。稍顿。我说一下好吗？ <br /><font color="#ff0000">Athena</font>: (有点冷淡）请便。 <br /><font color="#0066ff">Euripides</font>: 你真好。(<font color="#0066ff">Euripides</font>清了清自已的嗓子）昨晚，当口令和验证器在我脑子里转的时候，我想去找出这个系统新的问题，我想我发现了一个很严重的问题。我下面就演示一下。假设你厌倦了 现在的工作，决定换一个。你想用公司的激光打印机打印求职信 ，把它们送给猎头和其它的雇主。于是你输入打印命令，命令去取得服务票，然后把票送到打印机。这是你认为它应该被送到的地方。实际上你并不知道你的请求被送到了正确的打印服务器。假设一些无耻的人——比如说你的老板——调整了系统，把你的请求送到了他办公室的打印机。他的打印服务不关心票的内容。它告诉你的工作站服务已准备好打印你的文件。打印命 令被送到了假的打印服务器，你有麻烦了。我从相反的方向表达了相同的问题。用口令和验证器，<em><font color="#0000cc"> Charon </font></em>能够保护的它的服务器防止错误的用户使用，但它不能保护它的用户 使用错误的服务器。系统需要为客户端程序提供一种验证服务器的方法，在它向服务器发送敏感信息之前。系统必须允许交互验证。但口令的方案解决了这个问题。让我们回到打印服务器的场景。我想要打印客户程序确认它送交的服务是合法的服务。这就是程序要做的。我输入打印命令并给出一个文件名。这时我已经有了打印服务票和口令。客户程序用密码生成了一个验证器，然后把验证器和票送给了假设的打印服务器。客户端这时还没有送打印文件，它在等待从服务的返回。真的服务收到票和验证器，把票解密并得到口令，然后用口令解开验证器。这样服务端做完了所有的认证。测试已经确认了我的身份。现在服务程序要准备一个响应包来证实 它自已的身份。它用口令加密了返回包，并把包送给了等待的客户端。客户端收到了包并试图用口令把它解开 。如果包被正确的解开得到了正确的服务器响应信息，客户端程序就知道了这个服务器是合法的服务器。然后 这时客户端向它发出打印命令。假设我的老板改变了一下系统使得他的打印机看起来好像是我想要用的那个。我的客户端送了票和验证器给它并等待它的响应。假冒的打印服务 无法生成正确的响应因为它无法把票解开并 得到口令。这样的话客户端就不会送打印命令给它因为客户端没有得到正确的响应。最后客户端放弃等待并退出。我的打印没有完成，但至少我的求职信不会放在我的对头的桌子上。好啊，我想我们有了<em><font color="#0000cc"> Charon </font></em>认证系统的坚实的基础。 <br /><font color="#ff0000">Athena</font>: 也许。不管怎么说，我不喜欢<em><font color="#0000cc"> Charon </font></em>这个名字。 <br /><font color="#0066ff"><font color="#0066ff">Euripides</font></font>: 你不喜欢吗？什么时候？ <br /><font color="#ff0000">Athena</font>: 我从来都不喜欢，因为它的名字听 起来没意义。有一天我和我哈迪斯（冥王 )叔叔谈到了这个，他推荐了另一个名字：冥王的三个头的看门狗。 <br /><font color="#0066ff">Euripides</font>: 啊，你是说“<em><font color="#0000cc">Cerberus</font></em>". <br /><font color="#ff0000">Athena</font>: 你说什么语 言啊！"<em><font color="#0000cc">Cerberus</font></em>"实际上是…… <br /><font color="#0066ff">Euripides</font>: 哦，不叫这个吗？ <br /><font color="#ff0000">Athena</font>: 当然，谁让你是罗马人！而我是希腊人，它是一条希腊的看门狗，它的名字是“<em><font color="#0000cc"> Kerberos </font></em>”，“<em><font color="#0000cc"> Kerberos </font></em>”是“K”打头的。 <br /><font color="#0066ff">Euripides</font>: 好吧，好吧，别发火。我同意这个名字。实际上，它有一 个好的脖环。再见吧，<em><font color="#0000cc"> Charon </font></em>，欢迎你，<font color="#0000cc"><em> Kerberos </em></font><font color="#000000">。</font><br /><br /><strong>后 记</strong><br />这篇对话是于1988年写的，是为了帮助读者理解<em><font color="#0000cc"> Kerberos </font></em>V4的运行方式。经过了这么多年，它仍然非常好的服务于此。当我把这篇文章转换成HTML的时候 ，我惊讶的发现这个文档对<em><font color="#0000cc"> Kerberos </font></em>V5仍然非常有用。虽然很多东西改变了，但核心概念并没有变。实际上，<em><font color="#0000cc"> Kerberos </font></em>V5对 <em><font color="#0000cc">Kerberos </font></em>只做了两处改变。<br />第一处改变是因为意识到验证器用少于五分钟的有效期不足以防止攻击者进行重演，如果攻击者是用一个程序自动的截取票和验证器并进行 重演的话。在 <em><font color="#0000cc">Kerberos </font></em>V5中，验证器真正的只能用一次因为服务器用“重演缓冲区”保存了最近一次提交的验证器的信息。如果攻击者试图截取验证器并重用它，“重演缓冲区”会发现验证器已经被提交了。 <br />第二个主要改变是<em><font color="#0000cc"> Kerberos </font></em>送给<em><b>kinit</b></em>服务票的时候，票不再是用用户的口令加密。它已经用票据授权服务的口令加过密了。票据授权服务的票被用来获取其它票的时候，它直接就被传输了。因此票不需要再用用户的 口令加密一次。（服务器响应的其它部分，如口令，仍然是用用户的口令加密的）一个类似的改变也应用到 票据授权服务协议；从票据授权服务返回的票也不再用票据授权服务的口令来加密了，因为它所包含的票已经被对应的服务的口令加过密了。举例来说，<em><font color="#0000cc"> Kerberos </font></em>V4的包像这样： <br /><font color="#660066">KDC_REPLY = {TICKET, client, server, K_session}K_user</font><br />意思是：｛｝中的内容是用K_user来加密的。 <br /><font color="#660066">TICKET = {client, server, start_time, lifetime, K_session}K_server</font><br />在<em><font color="#0000cc"> Kerberos </font></em>V5中，KDC_REPLY现在看起来像这样： <br /><font color="#660066">KDC_REPLY = TICKET, {client, server, K_session}K_user</font><br />(注意：票已经 不再用K_user来加密了) <br />当然， <em><font color="#0000cc">Kerberos </font></em>V5中还有许多新特性。用户可以在另一个网络中安全的 提交他们的票；并且，用户可以把他们的一部分认证权转给服务器，这样服务器就可以作为用户的代理。其它 的新特性包括：用更好的加密算法替换了DES加密算法，如三重DES加密。读者如果对V4与V5的变化感兴趣的话 ，可以读一下“</font>
				<a href="http://web.mit.edu/%20Kerberos%20/www/papers.html">
						<font size="2">
								<font color="#002c99">The Evolution of the </font>
								<font color="#0000cc">Kerberos </font>
								<font color="#002c99">Authentication System</font>
						</font>
				</a>
				<font size="2">”，作者是Cliff Neumann和 Theodore Tso。我希望你能对这篇介绍<em><font color="#0000cc"> Kerberos </font></em>协议的文章感兴趣。我祝愿你在未来的探索中更进一步。</font>
		</p>
<img src ="http://www.blogjava.net/errorfun/aggbug/86563.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/errorfun/" target="_blank">errorfun</a> 2006-12-09 18:07 <a href="http://www.blogjava.net/errorfun/articles/86563.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]SSL -- 安全套接层的工作原理</title><link>http://www.blogjava.net/errorfun/articles/86562.html</link><dc:creator>errorfun</dc:creator><author>errorfun</author><pubDate>Sat, 09 Dec 2006 10:06:00 GMT</pubDate><guid>http://www.blogjava.net/errorfun/articles/86562.html</guid><wfw:comment>http://www.blogjava.net/errorfun/comments/86562.html</wfw:comment><comments>http://www.blogjava.net/errorfun/articles/86562.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/errorfun/comments/commentRss/86562.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/errorfun/services/trackbacks/86562.html</trackback:ping><description><![CDATA[
		<p>
				<font size="2">[出处:http://www.yesky.com/ServerIndex/77131904641400832/20040426/1791610.shtml]</font>
		</p>
		<p>
				<strong>
						<font color="#0000ff" size="2">密钥密码系统介绍</font>
				</strong>
		</p>
		<p>
				<font size="2">　　这篇文章向大家阐述了Netscape公司是如何使用RSA的公用密钥密码系统来实现因特网安全的。Netscape的安全套接层的实现就利用了这篇文章中所讨论的技术。<br />　　RSA的公用密钥密码系统广泛地应用于计算机工业的认证和加密方面。Netscape得到RSA数据安全公司的许可可以使用公用密钥密码系统以及其它产品，尤其是认证方面的产品。<br />　　公用密钥加密技术使用不对称的密钥来加密和解密，每对密钥包含一个公钥和一个私钥，公钥是公开，而且广泛分布的，而私钥从来不公开，只有自己知道。<br />　　用公钥加密的数据只有私钥才能解密，相反的，用私钥加密的数据只有公钥才能解密，正是这种不对称性才使得公用密钥密码系统那么有用。</font>
		</p>
		<p>
				<strong>
						<font color="#0000ff" size="2">使用公用密钥密码系统进行认证</font>
				</strong>
		</p>
		<p>
				<font size="2">　　认证是一个验证身份的过程，目的是使一个实体能够确信对方是他所声称的实体。下面的例子包括Alice和Bob，并且向我们演示了如何使用公用密钥密码系统来轻易的验证身份。下面的 {something}key 表示something 已经用密钥 key 加密或解密。<br />　　假设Alice要认证Bob，Bob有一个密钥对，即一个公钥和一个私钥，Bob透露给Alice他的公钥（至于他是怎么做的将在以后讨论）。然后Alice产生一段随机的消息，然后把它发给Bob。<br />　　</font>
				<font size="2">
						<font color="#ff0000">A--&gt;B random--message<br /></font>
						<br />　　Bob用自己的私钥来加密这段消息，然后把加密后的消息返回给Alice。<br />　　</font>
				<font size="2">
						<font color="#ff0000">B--&gt;A {random--message}bobs--private--key<br /></font>
						<br />　　Alice接到了这段消息，然后用Bob以前发过来的公钥来解密。她把解密后的消息和原始的消息做比较，如果匹配的话，她就知道自己正在和Bob通信。一个入侵者应该不知道Bob的私钥，因此就不能正确的加密那段Alice要检查的随机消息。<br />　　但是，等一下，还有......<br />　　除非你确切的知道你在加密什么，否则用你的私钥加密一些东西，然后发给别人永远不是一件好事。这是因为加密后的数据可能会背叛你（记住，只有你能加密，因为只有你才有密钥）。<br />　　所以，我们不加密Alice发送的原始消息，取而代之的是，由Bob构造一个消息信息段，然后加密它。消息信息段是从随机消息中以某种方式提取出来的，并且具有以下特点：<br />　　</font>
				<font size="2">
						<font color="#ff6600">
								<u>信息段很难逆转，任何假冒Bob的人不能从信息段得到原始消息 <br /></u>      <u>假冒者无法找到具有相同信息段的不同消息</u></font>
						<br />　　</font>
				<font size="2">
						<u>
								<font color="#ff6600">通过使用信息段，Bob能够保护自己。他首先计算出Alice发给他的随机消息的信息段并加密，然后把加密后的信息段返回给Alice，Alice可以计算出相同的信息段，通过解密Bob的消息然后对比一下就可以认证Bob的身份。<br /><br /></font>
						</u>      近一点......<br />　　刚才描述的技术称为数字签名。Bob为Alice产生的消息签名，这样做其实和加密Alice产生的随机消息一样危险。因此我们的认证协议需要一次以上的变形。部分（或者全部）的数据需要由Bob产生。<br />　　</font>
				<font size="2">
						<font color="#ff0000">A--&gt;B hello,are you bob?<br />　　B--&gt;A Alice,This Is bob{digest[Alice,This Is Bob]}bobs-private-key<br /></font>
						<br />　　当Bob使用这个协议的时候，他知道自己发给Alice的是什么消息，并且不介意签名。他首先发送没有加密的消息“Alice,This Is Bob。”然后发送加密的信息段。Alice能够轻易的判断Bob是Bob，并且Bob没有签任何他不愿意签的东西。</font>
		</p>
		<p>
				<br />
				<font size="2">
						<strong>
								<font color="#0000ff">分发公钥</font>
						</strong>
						<br />
						<br />　　Bob如何以一种可信赖的方式分发他的公钥呢？我们假设认证协议是这个样子的：<br />　　</font>
				<font size="2">
						<font color="#ff0000">A--&gt;B hello<br />　　B--&gt;A Hi, I'm Bob, bobs-public-key<br />　　A--&gt;B prove it<br />　　B--&gt;A Alice, This Is bob{ digest[Alice, This Is Bob] } bobs-private-key<br /></font>
						<br />　　如果使用这个协议的话，任何人都可以是Bob。你需要的只是一个公钥和私钥，你跟Alice慌称你是Bob，接着你用自己的公钥代替Bob的公钥，然后你通过用你的私钥加密的东西来证明，这样Alice就不能分辨出你不是Bob。<br />　　为了解决这个问题，标准化组织发明了一个叫做证书的东西，一个证书包括下面的一些内容：<br />　　</font>
				<font color="#ff9900">
						<font size="2">
								<u>证书发行者的名字 <br /></u>　　</font>
						<font size="2">
								<u>证书发送给的团体 <br /></u>　　</font>
						<font size="2">
								<u>主题的公钥 <br /></u>　　<u>时间戳</u></font>
				</font>
				<font size="2">
						<br />
						<br />　　证书是由证书发行者的私钥签名的，每个人都知道证书发行者的公钥（即证书发行者有一个证书，等等）。证书是一种把公钥绑定到名字的标准方式。<br />　　通过使用证书这种技术，每个人都可以通过检查Bob的证书来判断Bob是不是伪造的。假设Bob严格的控制着他的私钥，并且的确是Bob得到了他的证书，那么一切都好。下面是修订后的协议：<br />　　</font>
				<font size="2">
						<font color="#ff0000">A--&gt;B hello<br />　　B--&gt;A Hi, I'm Bob, bobs-certificate<br />　　A--&gt;B prove it<br />　　B--&gt;A Alice, This Is bob{ digest[Alice, This Is Bob] } bobs-private-key<br /></font>
						<br />　　当Alice收到Bob的第一条消息，她可以检查证书，核实签名（如上，使用信息段和公钥加密），然后，核实主题（Bob的名字）来判断那是不是真的Bob。这样她就相信公钥是Bob的公钥，然后要求Bob证明他的身份。Bob则重新进行一次上面的相同过程，计算消息的信息段，签名之后发给Alice，Alice可以用从证书得到的公钥检查Bob的消息信息段，从而判断Bob的身份。<br /><br />一个坏家伙 - 我们不妨叫他Mallet - 可以做下面的事情：<br />　　</font>
				<font size="2">
						<font color="#ff0000">A--&gt;M hello<br />　　M--&gt;A Hi, I'm Bob, bobs-certificate<br />　　A--&gt;M prove it<br />　　M--&gt;A 不能建立一个令甲相信的从乙的消息。<br /></font>
						<br />　　但是Mallet在最后的消息中不能满足Alice。Mallet没有Bob的私钥，所以他无法构造一条使Alice相信来自Bob的消息。</font>
		</p>
		<p>
				<strong>
						<font color="#0000ff" size="2">交换密码</font>
				</strong>
		</p>
		<p>
				<font size="2">　　一旦Alice认证了Bob，她就可以做另外一件事-她能发给一条只有Bob才能解码的消息：<br />　　</font>
				<font size="2">
						<font color="#ff0000">A--&gt;B {secret}bobs-public-key<br /></font>
						<br />　　发现这个秘密的唯一方法就是用Bob的私钥来解密上面的消息，交换秘密是公用密钥密码系统的另一种强大的用法。即使Alice和Bob之间的通信被监视，除了Bob，也没有人能够得到秘密。<br />　　这项技术加强了因特网的安全性，它把这个密码当作另一个密钥，但是这时它是对称性密码系统算法的密钥（如DES，RC4，IDEA）。Alice知道这个秘密，因为这是自己在发送给Bob之前产生的。Bob知道这个秘密，因为Bob有私钥，能够解密Alice的消息。因为他们都知道这个秘密，所以他们就可以初始化一个对称的密码算法然后开始传输用它加密的消息。下面是订正的协议：<br />　　</font>
				<font size="2">
						<font color="#ff0000">A--&gt;B hello<br />　　B--&gt;A Hi, I'm Bob, bobs-certificate<br />　　A--&gt;B prove it<br />　　B--&gt;A Alice, This Is bob{ digest[Alice, This Is Bob] } bobs-private-key<br />　　A--&gt;B ok bob, here is a secret {secret} bobs-public-key<br />　　B--&gt;A {some message}secret-key</font>
						<br />
						<br />　　secret-key 的计算取决于协议的定义，但是它可以简化成一个 secret 的副本。<br />　　你说什么？<br />　　Mallet的袋子里有很多诡计。虽然Mallet不能发现Alice和Bob交换的秘密，但是他可以干预并且破坏他们的对话。举例来说，如果Mallet位于Alice和Bob，他可以选择让大多数的消息返回以及向前继续传输没有改变，但是破坏了特定位的消息（这对他来说很容易，因为他知道Alice和Bob之间通信的协议）。<br />　　</font>
				<font size="2">
						<font color="#ff0000">A--&gt;M hello<br />　　M--&gt;B hello<br />B--&gt;M Hi, I'm Bob, bobs-certificate<br />　　M--&gt;A Hi, I'm Bob, bobs-certificate<br />　　A--&gt;M prove it<br />　　M--&gt;B prove it<br />　　B--&gt;M Alice, This Is bob{ digest[Alice, This Is Bob] } bobs-private-key<br />　　M--&gt;A Alice, This Is bob{ digest[Alice, This Is Bob] } bobs-private-key<br />　　A--&gt;M ok bob, here is a secret {secret} bobs-public-key<br />　　M--&gt;B ok bob, here is a secret {secret} bobs-public-key<br />　　B--&gt;M {some message}secret-key<br />　　M--&gt;A Garble[ {some message}secret-key ]</font>
						<br />
						<br />　　Mallet一直让数据没有改变的通过，直到Alice和Bob分享一个秘密。然后Mallet通过改变Bob发送给Alice的消息来进入这个方式中。这时候Alice是相信Bob的，因此她就可能相信这个改变的消息，然后按照它来做。注意Mallet并不知道这个秘密-他能做的所有事就是破坏用这个秘密的密钥加密的数据。他可能不能利用这个协议制造出一条有效的消息，但是下一次，他可能幸运一点。<br />　　为了防止这种破坏，Alice和Bob在他们的协议中引入了一种消息认证码（MAC）。MAC是根据秘密的密钥和传输的数据计算出来的，上面描述的信息段算法的属性正好可以用于构造抵抗Mallet的MAC功能。<br />　　<font color="#ff0000">MAC := Digest[ some message, secret ]</font></font>
		</p>
		<p>
				<font size="2">　　因为Mallet不知道这个秘密的密钥，所以他无法计算出这个信息段的正确数值。即使Mallet随机的改变消息，如果信息段数据很大的话，他成功的可能性也很小。举例来说，通过使用MD5（RSA公司发明的一种很好的密码信息段算法），Alice和Bob能和他们的消息一起发送128位的MAC值。Mallet猜中这个正确的MAC值的几率是1/18，446，744，073，709，551，616，约等于零。<br />　　下面是样本协议，又订正了一次：<br /></font>
				<font color="#ff0000" size="2">　　A--&gt;B hello<br />　　B--&gt;A Hi, I'm Bob, bobs-certificate<br />　　A--&gt;B prove it<br />　　B--&gt;A {digest[Alice, This Is Bob] } bobs-private-key <br />　ok bob, here is a secret {secret} bobs-public-key<br />　　{some message,MAC}secret-key</font>
		</p>
		<p>
				<font size="2">　　Mallet现在有麻烦了，Mallet可以改变任何的消息，但是MAC的计算将揭露他的欺诈行为。Alice和Bob能发现伪造的MAC值并停止会话，Mallet就不能伪造Bob的消息了。</font>
		</p>
		<p>
				<font size="2">　　这是什么时候的事？</font>
		</p>
		<p>
				<font size="2">　　最后的，但是同样重要的是要防范Mallet鹦鹉学舌。如果Mallet记录了会话的过程，他虽然可能不知道会话的内容，但是他可以重放这些会话。实际上，Mallet能在Alice和Bob之间做一些真正龌龊的事。解决的办法就是从会话的双方因如随机因素。<br /></font>
		</p>
<img src ="http://www.blogjava.net/errorfun/aggbug/86562.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/errorfun/" target="_blank">errorfun</a> 2006-12-09 18:06 <a href="http://www.blogjava.net/errorfun/articles/86562.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]SSL、TLS、WTLS原理</title><link>http://www.blogjava.net/errorfun/articles/86561.html</link><dc:creator>errorfun</dc:creator><author>errorfun</author><pubDate>Sat, 09 Dec 2006 10:05:00 GMT</pubDate><guid>http://www.blogjava.net/errorfun/articles/86561.html</guid><wfw:comment>http://www.blogjava.net/errorfun/comments/86561.html</wfw:comment><comments>http://www.blogjava.net/errorfun/articles/86561.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/errorfun/comments/commentRss/86561.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/errorfun/services/trackbacks/86561.html</trackback:ping><description><![CDATA[
		<p>[出处：<a href="http://www.chinaitlab.com/www/news/article_show.asp?id=7319">http://www.chinaitlab.com/www/news/article_show.asp?id=7319</a>]</p>
		<p>
				<strong>
						<font color="#0000ff">一 前言 <br /></font>
				</strong>　　<br />　　首先要澄清一下名字的混淆： <br />　　1 SSL(Secure Socket Layer)是netscape公司设计的主要用于web的安全传输协议。这种协议在WEB上获得了广泛的应用。 <br />　　2 IETF(www.ietf.org)将SSL作了标准化，即RFC2246,并将其称为TLS（Transport Layer Security），从技术上讲，TLS1.0与SSL3.0的差别非常微小。由于本文中没有涉及两者间的细小差别，本文中这两个名字等价。 <br />　　3 在WAP的环境下，由于手机及手持设备的处理和存储能力有限，wap论坛（www.wapforum.org）在TLS的基础上做了...S协议（Wireless Transport Layer Security），以适应无线的特殊环境。 <br />　　<br />　　我们从各式各样的文章中得知，SSL可以用于保密的传输，这样我们与web server之间传输的消息便是“安全的”。 <br />　　而这种“安全”究竟是怎么实现的，最终有能实现多大程度的保密？本文希望能用通俗的语言阐明其实现原理。 <br />　　<br />　　<br /><strong><font color="#0000ff">二 整体结构概览</font></strong><br />　　<br />　　SSL是一个介于HTTP协议与TCP之间的一个可选层，其位置大致如下： <br />　　<br />　　<font color="#ff0000">－－－－－－－－－ <br />　　| HTTP | <br />　　－－－－－－－－－ <br />　　| SSL | <br />　　－－－－－－－－－ <br />　　| TCP | <br />　　－－－－－－－－－ <br />　　| IP | <br />　　－－－－－－－－－ <br /></font>　　<br />　　如果利用SSL协议来访问网页，其步骤如下： <br />　　用户：在浏览器的地址栏里输入https://www.sslserver.com <br />　　HTTP层：将用户需求翻译成HTTP请求，如 <br />　　<font color="#ff0000">GET /index.htm HTTP/1.1 <br />　　Host http://www.sslserver.com</font><br />　　<br />　　<strong>SSL层：</strong>借助下层协议的的信道安全的协商出一份加密密钥，并用此密钥来加密HTTP请求。 <br />　　<strong>TCP层：</strong>与web server的443端口建立连接，传递SSL处理后的数据。 <br />　　<br />　　接收端与此过程相反。 <br />　　<br />　　SSL在TCP之上建立了一个加密通道，通过这一层的数据经过了加密，因此达到保密的效果。 <br />　　<br />　　SSL协议分为两部分：Handshake Protocol和Record Protocol,。其中Handshake Protocol用来协商密钥，协议的大部分内容就是通信双方如何利用它来安全的协商出一份密钥。 Record Protocol则定义了传输的格式。 <br />　　<br />　　<br /><strong><font color="#0000ff">三 需要的加密方面的基础知识</font></strong><br /><br />　　了解SSL原理需要一点点加密的概念，这里把需要的概念做一下简单阐述： <br />　　<br />　　加密一般分为三类，对称加密，非对称加密及单向散列函数。 <br />　　<br />　　对称加密：又分分组密码和序列密码。 <br />　　分组密码是将明文按一定的位长分组，明文组经过加密运算得到密文组，密文组经过解密运算 <br />　　（加密运算的逆运算），还原成明文组。 <br />　　序列密码是指利用少量的密钥（制乱元素）通过某种复杂的运算（密码算法）产生大量的伪随机位流，用于对明文位流的加密。 <br />　　解密是指用同样的密钥和密码算法及与加密相同的伪随机位流，用以还原明文位流。 <br />　　<br />　　CBC(Cipher Block Chaining)模式这个词在分组密码中经常会用到，它是指一个明文分组在被加密之前要与前一个的密文分组进行异或运算。当加密算法用于此模式的时候除密钥外，还需协商一个初始化向量（IV），这个IV没有实际意义，只是在第一次计算的时候需要用到而已。采用这种模式的话安全性会有所提高。 <br />　　<br />　　分组密码的典型例子为DES,RC5,IDEA。 <br />　　序列密码的典型例子为RC4。 <br />　　<br />　　<strong>公钥加密：</strong><br />　　简单的说就是加密密钥与解密密钥不同，分私钥和公钥。这种方法大多用于密钥交换，RSA便是一个我们熟知的例子。 <br />　　还有一个常用的称作DH，它只能用于密钥交换，不能用来加密。 <br />　　<br />　　<strong>单向散列函数： <br /></strong>　　由于信道本身的干扰和人为的破坏，接受到的信息可能与原来发出的信息不同，一个通用的办法就是加入校验码。 <br />　　单向散列函数便可用于此用途，一个典型的例子是我们熟知的MD5,它产生128位的摘要，在现实中用的更多的是安全散列算法（SHA），SHA的早期版本存在问题，目前用的实际是SHA－1，它可以产生160位的摘要，因此比128位散列更能有效抵抗穷举攻击。 <br />　　<br />　　由于单向散列的算法都是公开的，所以其它人可以先改动原文，再生成另外一份摘要。解决这个问题的办法可以通过HMAC（RFC 2104）,它包含了一个密钥，只有拥有相同密钥的人才能鉴别这个散列。 <br />　　<br />　　<br /><strong><font color="#0000ff">四 密钥协商过程 <br /></font></strong>　　<br />　　由于对称加密的速度比较慢，所以它一般用于密钥交换，双方通过公钥算法协商出一份密钥，然后通过对称加密来通信，当然，为了保证数据的完整性，在加密前要先经过HMAC的处理。 <br />　　<br />　　<br />　　SSL缺省只进行server端的认证，客户端的认证是可选的。以下是其流程图（摘自TLS协议）。 <br />　　<br />　　<br />　　<font color="#ff0000">Client Server <br />　　<br />　　Clienth*llo --------&gt; <br />　　Serverh*llo <br />　　Certificate* <br />　　ServerKeyExchange* <br />　　CertificateRequest* <br />　　&lt;-------- Serverh*lloDone <br />　　Certificate* <br />　　ClientKeyExchange <br />　　CertificateVerify* <br />　　[ChangeCipherSpec] <br />　　Finished --------&gt; <br />　　[ChangeCipherSpec] <br />　　&lt;-------- Finished <br />　　Application Data &lt;-------&gt; Application Data <br /></font>　　<br />　　简单的说便是：SSL客户端（也是TCP的客户端）在TCP链接建立之后，发出一个Clienth*llo来发起握手，这个消息里面包含了自己可实现的算法列表和其它一些需要的消息，SSL的服务器端会回应一个Serverh*llo，这里面确定了这次通信所需要的算法，然后发过去自己的证书（里面包含了身份和自己的公钥）。Client在收到这个消息后会生成一个秘密消息，用SSL服务器的公钥加密后传过去，SSL服务器端用自己的私钥解密后，会话密钥协商成功，双方可以用同一份会话密钥来通信了。 <br />　　<br />　　<br /><strong><font color="#0000ff">五 密钥协商的形象化比喻 <br /></font></strong>　　<br />　　如果上面的说明不够清晰，这里我们用个形象的比喻，我们假设A与B通信，A是SSL客户端，B是SSL服务器端，加密后的消息放在方括号[]里，以突出明文消息的区别。双方的处理动作的说明用圆括号（）括起。 <br />　　<br />　　<font color="#ff0000">A：我想和你安全的通话，我这里的对称加密算法有DES,RC5,密钥交换算法有RSA和DH，摘要算法有MD5和SHA。 <br />　　<br />　　B：我们用DES－RSA－SHA这对组合好了。 <br />　　这是我的证书，里面有我的名字和公钥，你拿去验证一下我的身份（把证书发给A）。 <br />　　目前没有别的可说的了。 <br />　　<br />　　A：（查看证书上B的名字是否无误，并通过手头早已有的CA的证书验证了B的证书的真实性，如果其中一项有误，发出警告并断开连接，这一步保证了B的公钥的真实性） <br />　　（产生一份秘密消息，这份秘密消息处理后将用作加密密钥，加密初始化向量和hmac的密钥。将这份秘密消息-协议中称为per_master_secret-用B的公钥加密，封装成称作ClientKeyExchange的消息。由于用了B的公钥，保证了第三方无法窃听） <br />　　我生成了一份秘密消息，并用你的公钥加密了，给你（把ClientKeyExchange发给B） <br />　　注意，下面我就要用加密的办法给你发消息了！ <br />　　（将秘密消息进行处理，生成加密密钥，加密初始化向量和hmac的密钥） <br />　　[我说完了] <br />　　<br />　　B：（用自己的私钥将ClientKeyExchange中的秘密消息解密出来，然后将秘密消息进行处理，生成加密密钥，加密初始化向量和hmac的密钥，这时双方已经安全的协商出一套加密办法了） <br />　　注意，我也要开始用加密的办法给你发消息了！ <br />　　[我说完了] <br />　　<br />　　A: [我的秘密是...] <br />　　<br />　　B: [其它人不会听到的...] <br /></font>　　<br />　　<br /><strong><font color="#0000ff">六 加密的计算 <br /><br /></font></strong>　　上一步讲了密钥的协商，但是还没有阐明是如何利用加密密钥，加密初始化向量和hmac的密钥来加密消息的。 <br />　　其实其过程不过如此： <br />　　1 借助hmac的密钥，对明文的消息做安全的摘要处理，然后和明文放到一起。 <br />　　2 借助加密密钥，加密初始化向量加密上面的消息。 <br />　　<br />　　<br /><strong><font color="#0000ff">七 安全性</font></strong><br /><br />　　SecurityPortal在2000年底有一份文章《The End of SSL and SSH?》激起了很多的讨论， <br />　　目前也有一些成熟的工具如dsniff（http://www.monkey.org/~dugsong/dsniff/）可以 <br />　　通过man in the middle攻击来截获https的消息。 <br />　　<br />　　从上面的原理可知，SSL的结构是严谨的，问题一般出现在实际不严谨的应用中。常见的攻击就是 <br />　　middle in the middle攻击，它是指在A和B通信的同时，有第三方C处于信道的中间，可以完全 <br />　　听到A与B通信的消息，并可拦截，替换和添加这些消息。 <br />　　<br />　　1 SSL可以允许多种密钥交换算法，而有些算法，如DH，没有证书的概念，这样A便无法验证B的公钥 <br />　　和身份的真实性，从而C可以轻易的冒充，用自己的密钥与双方通信，从而窃听到别人谈话的内容。 <br />　　而为了防止middle in the middle攻击，应该采用有证书的密钥交换算法。 <br />　　2 有了证书以后，如果C用自己的证书替换掉原有的证书之后，A的浏览器会弹出一个警告框进行警告，但又有多少人会注意这个警告呢？ <br />　　3 由于美国密码出口的限制，IE，netscape等浏览器所支持的加密强度是很弱的，如果只采用浏览器自带的加密功能的话，理论上存在被破解可能。 <br />　　<br />　　<br /><strong><font color="#0000ff">八 代理</font></strong><br /><br />　　下面探讨一下SSL的代理是怎样工作的(可参见[6])。这可能与你开始想的不太一样：） <br />　　当在浏览器里设置了https的代理，而且在浏览器里输入了https://www.example.com之后， <br />　　浏览器会与proxy建立tcp链接，然后向其发出这么一段消息： <br />　<font color="#ff0000">　CONNECT server.example.com:443 HTTP/1.1 <br />　　Host: server.example.com:443 </font><br />　　<br />　　然后proxy会向webserver端建立tcp连接,之后，这个代理便完全成了个内容转发装置。浏览器 <br />　　与web server会建立一个安全通道，因此这个安全通道是端到端的，尽管所有的信息流过了proxy, <br />　　但其内容proxy是无法解密和改动的（当然要由证书的支持，否则这个地方便是个man in the middle攻击的好场所，见上面的讨论）。 <br />　　<br />　　<br /><strong><font color="#0000ff">九 关于证书</font></strong><br />　　<br />　　注意，如果对于一般的应用，管理员只需生成“证书请求”（后缀大多为.csr），它包含你的名字和公钥，然后把这份请求交给诸如verisign等有CA服务公司（当然，连同几百美金）， <br />　　你的证书请求经验证后，CA用它的私钥签名，形成正式的证书发还给你。管理员再在web server上导入这个证书就行了。如果你不想花那笔钱，或者想了解一下原理，可以自己做CA。 <br />　　从ca的角度讲，你需要CA的私钥和公钥。从想要证书的服务器角度将，需要把服务器的证书请求交给CA. <br />　　<br />　　如果你要自己做CA，别忘了客户端需要导入CA的证书（CA的证书是自签名的，导入它意味着你“信任”这个CA签署的证书）。 <br />　　而商业CA的一般不用，因为它们已经内置在你的浏览器中了。 <br />　　<br />　　<br /><strong><font color="#0000ff">十 wtls <br /></font></strong>　　<br />　　在WAP的环境中，也有安全加密的需求，因此wapforum参照在WWW世界里最为流行的SSL协议设计了WTLS.从原理上说，这份协议与SSL是基本相同的，但在具体的地方作了许多改动。这些改动的大多没有什么技术上的需要，而是由于考虑到手持设备运算与存储的局限而尽量做了简化。不过我的感觉是这些改动意义实在不大，其获得的计算和存储上节省出来的时间和空间并不多。在硬件速度突飞猛进的时代，这种改动能获得的好处也许并不很多（一个新的协议便需要大量新的投入，而且与原有体制并不兼容，关于这点有文章[7]做了精彩阐述，可参看）。 <br />　　<br />　　这里我简单举一些SSL与WTLS的差别。 <br />　　<br />　　1 WTLS在一般udp这类不可靠信道之上工作，因此每个消息里要有序列号，协议里也要靠它来处理丢包，重复等情况。 <br />　　此外，拒绝服务攻击也因此变得更加容易。 <br />　　2 WTLS建立的安全连接是在wap网关和手持设备之间，wap网关和web server之间如果也要保密，便要采再用SSL，即在这种模型中无法实现端到端的加密。 <br />　　<br /><font color="#ff0000">　　---------- ------------- --------- <br />　　| Mobile |-----------&gt;| WAP |----------&gt;| WEB | <br />　　| Device |&lt;-----------| Gateway |&lt;----------|Server | <br />　　| | WTLS | | SSL | | <br />　　---------- ------------- --------- <br /></font>　　<br />　　3 WTLS协议里加了一种成为key_refresh的机制,当传递了一定数量数据包后，双方通过同样的算法将自己的密钥做一下更新。付出了很小的代价，安全性得以增强。 </p>
<img src ="http://www.blogjava.net/errorfun/aggbug/86561.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/errorfun/" target="_blank">errorfun</a> 2006-12-09 18:05 <a href="http://www.blogjava.net/errorfun/articles/86561.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]防火墙的工作原理</title><link>http://www.blogjava.net/errorfun/articles/86560.html</link><dc:creator>errorfun</dc:creator><author>errorfun</author><pubDate>Sat, 09 Dec 2006 10:03:00 GMT</pubDate><guid>http://www.blogjava.net/errorfun/articles/86560.html</guid><wfw:comment>http://www.blogjava.net/errorfun/comments/86560.html</wfw:comment><comments>http://www.blogjava.net/errorfun/articles/86560.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/errorfun/comments/commentRss/86560.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/errorfun/services/trackbacks/86560.html</trackback:ping><description><![CDATA[
		<p>
				<font color="#000099" size="2">什么是防火墙<br /><br />       </font>
				<span lang="EN-US" style="FONT-FAMILY: 宋体">
						<font size="2">防火墙就是一种过滤塞（目前你这么理解不算错），你可以让你喜欢的东西通过这个塞子，别的玩意都统统过滤掉。在网络的世界里，要由防火墙过滤的就是承载通信数据的通信包。 <br /><br />    天下的防火墙至少都会说两个词：Yes或者No。直接说就是接受或者拒绝。最简单的防火墙是以太网桥。但几乎没有人会认为这种原始防火墙能管多大用。大多数防火墙采用的技术和标准可谓五花八门。这些防火墙的形式多种多样：有的取代系统上已经装备的TCP/IP协议栈；有的在已有的协议栈上建立自己的软件模块；有的干脆就是独立的一套操作系统。还有一些应用型的防火墙只对特定类型的网络连接提供保护（比如SMTP或者HTTP协议等）。还有一些基于硬件的防火墙产品其实应该归入安全路由器一类。以上的产品都可以叫做防火墙，因为他们的工作方式都是一样的：分析出入防火墙的数据包，决定放行还是把他们扔到一边。 <br /><br />    所有的防火墙都具有IP地址过滤功能。这项任务要检查IP包头，根据其IP源地址和目标地址作出放行/丢弃决定。看看下面这张图，两个网段之间隔了一个防火墙，防火墙的一端有台UNIX计算机，另一边的网段则摆了台PC客户机。</font>
				</span>
		</p>
		<p>
				<span lang="EN-US" style="FONT-FAMILY: 宋体">
						<img alt=" " src="http://www.infosecurity.org.cn/content/firewall/pic/01_2_28_2a.jpg" onload="javascript: img_auto_size(this,450,true);" align="baseline" />
				</span>
		</p>
		<p>
				<span lang="EN-US" style="FONT-FAMILY: 宋体">
						<font size="2">    当PC客户机向UNIX计算机发起telnet请求时，PC的telnet客户程序就产生一个TCP包并把它传给本地的协议栈准备发送。接下来，协议栈将这个TCP包“塞”到一个IP包里，然后通过PC机的TCP/IP栈所定义的路径将它发送给UNIX计算机。在这个例子里，这个IP包必须经过横在PC和UNIX计算机中的防火墙才能到达UNIX计算机。 <br /><br />    现在我们“命令”（用专业术语来说就是配制）防火墙把所有发给UNIX计算机的数据包都给拒了，完成这项工作以后，“心肠”比较好的防火墙还会通知客户程序一声呢！既然发向目标的IP数据没法转发，那么只有和UNIX计算机同在一个网段的用户才能访问UNIX计算机了。 </font>
				</span>
		</p>
		<p>
				<span lang="EN-US" style="FONT-FAMILY: 宋体">
						<font size="2">
						</font>
						<img alt=" " src="http://www.infosecurity.org.cn/content/firewall/pic/01_2_28_2b.jpg" onload="javascript: img_auto_size(this,450,true);" align="baseline" />
						<br />
						<font size="2">还有一种情况，你可以命令防火墙专给那台可怜的PC机找茬，别人的数据包都让过就它不行。这正是防火墙最基本的功能：根据IP地址做转发判断。但要上了大场面这种小伎俩就玩不转了，由于黑客们可以采用IP地址欺骗技术，伪装成合法地址的计算机就可以穿越信任这个地址的防火墙了。不过根据地址的转发决策机制还是最基本和必需的。另外要注意的一点是，不要用DNS主机名建立过滤表，对DNS的伪造比IP地址欺骗要容易多了。 <br /><span style="FONT-FAMILY: 宋体"><font color="#000099"></font></span></font>
				</span>
		</p>
		<p>
				<span lang="EN-US" style="FONT-FAMILY: 宋体">
						<font size="2">
								<span style="FONT-FAMILY: 宋体">
										<font color="#000099">服务器TCP/UDP 端口过滤 <br /></font>
								</span>
						</font>
						<span lang="EN-US" style="FONT-FAMILY: 宋体">
								<br />
								<font size="2">    仅仅依靠地址进行数据过滤在实际运用中是不可行的，还有个原因就是目标主机上往往运行着多种通信服务，比方说，我们不想让用户采用 telnet的方式连到系统，但这绝不等于我们非得同时禁止他们使用SMTP/POP邮件服务器吧？所以说，在地址之外我们还要对服务器的TCP/ UDP端口进行过滤。 </font>
								<br />
								<img alt=" " src="http://www.infosecurity.org.cn/content/firewall/pic/01_2_28_2c.jpg" onload="javascript: img_auto_size(this,450,true);" align="baseline" />
						</span>
				</span>
		</p>
		<p>
				<span lang="EN-US" style="FONT-FAMILY: 宋体">
						<span lang="EN-US" style="FONT-FAMILY: 宋体">
								<font size="2">比如，默认的telnet服务连接端口号是23。假如我们不许PC客户机建立对UNIX计算机（在这时我们当它是服务器）的telnet连接，那么我们只需命令防火墙检查发送目标是UNIX服务器的数据包，把其中具有23目标端口号的包过滤就行了。这样，我们把IP地址和目标服务器TCP/UDP端口结合起来不就可以作为过滤标准来实现相当可靠的防火墙了吗？不，没这么简单。 <br /><font color="#000099"></font></font>
						</span>
				</span>
		</p>
		<p>
				<span lang="EN-US" style="FONT-FAMILY: 宋体">
						<span lang="EN-US" style="FONT-FAMILY: 宋体">
								<font size="2">
										<font color="#000099">客户机也有TCP/UDP端口 <br /></font>
										<br />    TCP/IP是一种端对端协议，每个网络节点都具有唯一的地址。网络节点的应用层也是这样，处于应用层的每个应用程序和服务都具有自己的对应“地址”，也就是端口号。地址和端口都具备了才能建立客户机和服务器的各种应用之间的有效通信联系。比如，telnet服务器在端口23侦听入站连接。同时telnet客户机也有一个端口号，否则客户机的IP栈怎么知道某个数据包是属于哪个应用程序的呢？ <br /><br />    由于历史的原因，几乎所有的TCP/IP客户程序都使用大于1023的随机分配端口号。只有UNIX计算机上的root用户才可以访问1024以下的端口，而这些端口还保留为服务器上的服务所用。所以，除非我们让所有具有大于1023端口号的数据包进入网络，否则各种网络连接都没法正常工作。<br /></font>
						</span>
				</span>
				<span lang="EN-US" style="FONT-FAMILY: 宋体">
						<span lang="EN-US" style="FONT-FAMILY: 宋体">
								<br />
								<font size="2">    这对防火墙而言可就麻烦了，如果阻塞入站的全部端口，那么所有的客户机都没法使用网络资源。因为服务器发出响应外部连接请求的入站（就是进入防火墙的意思）数据包都没法经过防火墙的入站过滤。反过来，打开所有高于1023的端口就可行了吗？也不尽然。由于很多服务使用的端口都大于1023，比如X client、基于RPC的NFS服务以及为数众多的非UNIX IP产品等（NetWare/IP）就是这样的。那么让达到1023端口标准的数据包都进入网络的话网络还能说是安全的吗？连这些客户程序都不敢说自己是足够安全的。 <br /><img alt=" " src="http://www.infosecurity.org.cn/content/firewall/pic/01_2_28_2d.jpg" onload="javascript: img_auto_size(this,450,true);" align="baseline" /></font>
						</span>
				</span>
				<span lang="EN-US" style="FONT-FAMILY: 宋体">
						<span lang="EN-US" style="FONT-FAMILY: 宋体">
								<font color="#000099" size="2">双向过滤 <br /></font>
								<span lang="EN-US" style="FONT-FAMILY: 宋体">
										<br />
										<font size="2">    OK，咱们换个思路。我们给防火墙这样下命令：已知服务的数据包可以进来，其他的全部挡在防火墙之外。比如，如果你知道用户要访问Web服务器，那就只让具有源端口号80的数据包进入网络： </font>
										<br />
										<img alt=" " src="http://www.infosecurity.org.cn/content/firewall/pic/01_2_28_2e.jpg" onload="javascript: img_auto_size(this,450,true);" align="baseline" />
								</span>
						</span>
				</span>
		</p>
		<p>
		</p>
		<p>
				<span lang="EN-US" style="FONT-FAMILY: 宋体">
						<span lang="EN-US" style="FONT-FAMILY: 宋体">
								<span lang="EN-US" style="FONT-FAMILY: 宋体">
										<font size="2">不过新问题又出现了。首先，你怎么知道你要访问的服务器具有哪些正在运行的端口号呢？ 象HTTP这样的服务器本来就是可以任意配置的，所采用的端口也可以随意配置。如果你这样设置防火墙，你就没法访问哪些没采用标准端口号的的网络站点了！反过来，你也没法保证进入网络的数据包中具有端口号80的就一定来自Web服务器。有些黑客就是利用这一点制作自己的入侵工具，并让其运行在本机的80端口！ <br /></font>
								</span>
						</span>
				</span>
		</p>
		<p>
				<span lang="EN-US" style="FONT-FAMILY: 宋体">
						<span lang="EN-US" style="FONT-FAMILY: 宋体">
								<span lang="EN-US" style="FONT-FAMILY: 宋体">
										<font size="2">
												<font color="#000099">检查ACK位 <br /></font>
												<br />    源地址我们不相信，源端口也信不得了，这个不得不与黑客共舞的疯狂世界上还有什么值得我们信任呢？还好，事情还没到走投无路的地步。对策还是有的，不过这个办法只能用于TCP协议。 <br /><br />    TCP是一种可靠的通信协议，“可靠”这个词意味着协议具有包括纠错机制在内的一些特殊性质。为了实现其可靠性，每个TCP连接都要先经过一个“握手”过程来交换连接参数。还有，每个发送出去的包在后续的其他包被发送出去之前必须获得一个确认响应。但并不是对每个TCP包都非要采用专门的ACK包来响应，实际上仅仅在TCP包头上设置一个专门的位就可以完成这个功能了。所以，只要产生了响应包就要设置ACK位。连接会话的第一个包不用于确认，所以它就没有设置ACK位，后续会话交换的TCP包就要设置ACK位了。 </font>
										<br />
										<img alt=" " src="http://www.infosecurity.org.cn/content/firewall/pic/01_2_28_2f.jpg" onload="javascript: img_auto_size(this,450,true);" align="baseline" />
								</span>
						</span>
				</span>
		</p>
		<p>
				<span lang="EN-US" style="FONT-FAMILY: 宋体">
						<span lang="EN-US" style="FONT-FAMILY: 宋体">
								<span lang="EN-US" style="FONT-FAMILY: 宋体">
										<font size="2">举个例子，PC向远端的Web服务器发起一个连接，它生成一个没有设置ACK位的连接请求包。当服务器响应该请求时，服务器就发回一个设置了ACK位的数据包，同时在包里标记从客户机所收到的字节数。然后客户机就用自己的响应包再响应该数据包，这个数据包也设置了ACK位并标记了从服务器收到的字节数。通过监视ACK位，我们就可以将进入网络的数据限制在响应包的范围之内。于是，远程系统根本无法发起TCP连接但却能响应收到的数据包了。 <br /><br />    这套机制还不能算是无懈可击，简单地举个例子，假设我们有台内部Web服务器，那么端口80就不得不被打开以便外部请求可以进入网络。还有，对UDP包而言就没法监视ACK位了，因为UDP包压根就没有ACK位。还有一些TCP应用程序，比如FTP，连接就必须由这些服务器程序自己发起。 <br /></font>
								</span>
						</span>
				</span>
		</p>
		<p>
				<span lang="EN-US" style="FONT-FAMILY: 宋体">
						<span lang="EN-US" style="FONT-FAMILY: 宋体">
								<span lang="EN-US" style="FONT-FAMILY: 宋体">
										<font size="2">
												<span style="FONT-FAMILY: 宋体">
														<font color="#000099">FTP带来的困难 </font>
												</span>
										</font>
										<span lang="EN-US" style="FONT-FAMILY: 宋体">
												<br />
												<font size="2">
														<br />    一般的Internet服务对所有的通信都只使用一对端口号，FTP程序在连接期间则使用两对端口号。第一对端口号用于FTP的“命令通道”提供登录和执行命令的通信链路，而另一对端口号则用于FTP的“数据通道”提供客户机和服务器之间的文件传送。 <br /><br />    在通常的FTP会话过程中，客户机首先向服务器的端口21（命令通道）发送一个TCP连接请求，然后执行LOGIN、DIR等各种命令。一旦用户请求服务器发送数据，FTP服务器就用其20端口 (数据通道)向客户的数据端口发起连接。问题来了，如果服务器向客户机发起传送数据的连接，那么它就会发送没有设置ACK位的数据包，防火墙则按照刚才的规则拒绝该数据包同时也就意味着数据传送没戏了。通常只有高级的、也就是够聪明的防火墙才能看出客户机刚才告诉服务器的端口，然后才许可对该端口的入站连接。 </font>
										</span>
								</span>
						</span>
				</span>
		</p>
		<p>
				<span lang="EN-US" style="FONT-FAMILY: 宋体">
						<span lang="EN-US" style="FONT-FAMILY: 宋体">
								<span lang="EN-US" style="FONT-FAMILY: 宋体">
										<span lang="EN-US" style="FONT-FAMILY: 宋体">
												<font size="2">
														<font color="#000099">
																<br />UDP端口过滤 <br /></font>
														<br />    好了，现在我们回过头来看看怎么解决UDP问题。刚才说了，UDP包没有ACK位所以不能进行ACK位过滤。UDP 是发出去不管的“不可靠”通信，这种类型的服务通常用于广播、路由、多媒体等广播形式的通信任务。NFS、DNS、WINS、NetBIOS-over-TCP/IP和 NetWare/IP都使用UDP。 <br /><br />    看来最简单的可行办法就是不允许建立入站UDP连接。防火墙设置为只许转发来自内部接口的UDP包，来自外部接口的UDP包则不转发。现在的问题是，比方说，DNS名称解析请求就使用UDP，如果你提供DNS服务，至少得允许一些内部请求穿越防火墙。还有IRC这样的客户程序也使用UDP，如果要让你的用户使用它，就同样要让他们的UDP包进入网络。我们能做的就是对那些从本地到可信任站点之间的连接进行限制。但是，什么叫可信任！如果黑客采取地址欺骗的方法不又回到老路上去了吗？ <br /><br />    有些新型路由器可以通过“记忆”出站UDP包来解决这个问题：如果入站UDP包匹配最近出站UDP包的目标地址和端口号就让它进来。如果在内存中找不到匹配的UDP包就只好拒绝它了！但是，我们如何确信产生数据包的外部主机就是内部客户机希望通信的服务器呢？如果黑客诈称DNS服务器的地址，那么他在理论上当然可以从附着DNS的UDP端口发起攻击。只要你允许DNS查询和反馈包进入网络这个问题就必然存在。办法是采用代理服务器。 <br /><br />    所谓代理服务器，顾名思义就是代表你的网络和外界打交道的服务器。代理服务器不允许存在任何网络内外的直接连接。它本身就提供公共和专用的DNS、邮件服务器等多种功能。代理服务器重写数据包而不是简单地将其转发了事。给人的感觉就是网络内部的主机都站在了网络的边缘，但实际上他们都躲在代理的后面，露面的不过是代理这个假面具。</font>
										</span>
								</span>
						</span>
				</span>
		</p>
		<p>
				<span lang="EN-US" style="FONT-FAMILY: 宋体">
						<span lang="EN-US" style="FONT-FAMILY: 宋体">
								<span lang="EN-US" style="FONT-FAMILY: 宋体">
										<span lang="EN-US" style="FONT-FAMILY: 宋体">
												<font size="2">
														<br />
												</font>
										</span>
										<font size="2">
												<font color="#000099">
														<span style="FONT-FAMILY: 宋体">小结 <br /><br />  </span>
												</font>
												<span style="FONT-FAMILY: 宋体">  IP地址可能是假的，这是</span>
										</font>
										<span lang="EN-US" style="FONT-FAMILY: 宋体">
												<font size="2">由于IP协议的源路有机制所带来的，这种机制告诉路由器不要为数据包采用正常的路径，而是按照包头内的路径传送数据包。于是黑客就可以使用系统的IP地址获得返回的数据包。有些高级防火墙可以让用户禁止源路由。通常我们的网络都通过一条路径连接ISP，然后再进入Internet。这时禁用源路由就会迫使数据包必须沿着正常的路径返回。 <br /><br />    还有，我们需要了解防火墙在拒绝数据包的时候还做了哪些其他工作。比如，防火墙是否向连接发起系统发回了“主机不可到达”的ICMP消息？或者防火墙真没再做其他事？这些问题都可能存在安全隐患。ICMP“主机不可达”消息会告诉黑客“防火墙专门阻塞了某些端口”，黑客立即就可以从这个消息中闻到一点什么气味。如果ICMP“主机不可达”是通信中发生的错误，那么老实的系统可能就真的什么也不发送了。反过来，什么响应都没有却会使发起通信的系统不断地尝试建立连接直到应用程序或者协议栈超时，结果最终用户只能得到一个错误信息。当然这种方式会让黑客无法判断某端口到底是关闭了还是没有使用。<br /></font>
										</span>
								</span>
						</span>
				</span>
		</p>
		<p>
				<span lang="EN-US" style="FONT-FAMILY: 宋体">
						<span lang="EN-US" style="FONT-FAMILY: 宋体">
								<span lang="EN-US" style="FONT-FAMILY: 宋体">
										<span lang="EN-US" style="FONT-FAMILY: 宋体">
												<font size="2">
														<font color="#ff0000" size="3">附录:Windows XP SP2防火墙的工作原理</font> <br /><br />    对于只使用浏览、电子邮件等系统自带的网络应用程序，Windows防火墙根本不会产生影响。也就是说，用IE、OutlookExpress等系统自带的程序进行网络连接，防火墙是默认不干预的。微软在设置防火墙内置规则时，已经为自家的应用程序开了“绿色通道”，所以装上SP2后，即使打开其防火墙并且启用“不允许例外”，无需将IE加到“例外”就能上网，而防火墙也不会询问是否要允许IE通过。 <br /><br /><br /><font color="#000099">SP2防火墙与第三方防火墙软件的区别</font><br /><br />　　仅就防火墙功能而言，Windows防火墙只阻截所有传入的未经请求的流量，对主动请求传出的流量不作理会。而第三方病毒防火墙软件一般都会对两个方向的访问进行监控和审核，这一点是它们之间最大的区别。如果入侵已经发生或间谍软件已经安装，并主动连接到外部网络，那么Windows防火墙是束手无策的。不过由于攻击多来自外部，而且如果间谍软件偷偷自动开放端口来让外部请求连接，那么Windows防火墙会立刻阻断连接并弹出安全警告，所以普通用户不必太过担心这点。这就好像宾馆里的房门一样——外面的人要进入必须用钥匙开门，而屋里的人要出门，只要拉一下门把手就可以了。</font>
										</span>
								</span>
						</span>
				</span>
		</p>
<img src ="http://www.blogjava.net/errorfun/aggbug/86560.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/errorfun/" target="_blank">errorfun</a> 2006-12-09 18:03 <a href="http://www.blogjava.net/errorfun/articles/86560.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>