计算机网络——自顶向下的方法第八章的学习
最后一章讲网安了。
梗概
介绍了网络安全中常见的两个通信主体:Alice 和 Bob,他们在一条随时会被窃听的信道上通信,如何保证数据不被第三人获取。
什么是网络安全
显然,Alice希望即使他们在一个不安全的媒体上进行通信,也只有 Bob 能够理解她所发送的报文,其中入侵者(入侵者名叫Trudy)能够在该媒体上截获从Alice向Bob传输的报文。
安全的通信应该具有以下特性:
- 机密性:仅有双方能知道他们发送的内容,即使中间通信信道能够随时被窃听。
- 完整性:Alice和Bob希望确保其通信的内容在传输过程中未被改变。
- 端点鉴别:即能确定对方确实是他所称的那个人。
- 运行安全性:确保服务器不会被入侵。
入侵者能够执行以下可能的行为:
- 窃听:随意读取信道上的内容。
- 篡改:截获一个包,并修改或删除报文的内容。

如我们将看到的那样,除非采取适当的措施,否则上述能力使入侵者可以用多种方式发动各种各样的安全攻击:窃听通信内容(可能窃取口令和数据),假冒另一个实体,“劫持” 一个正在进行的会话,通过使系统资源过载拒绝合法网络用户的服务请求等等。
应用密码学来提供机密性是不言而喻的,同时我们很快将看到它对于提供端点鉴别、 报文完整性也起到了核心作用,这使得密码学成为网络安全的基石。
密码学的原则
密码技术使得发送方可以伪装数据,使入侵者不能从截取到的数据中获得任何信息。当然,接收方必须能够从伪装的数据中恢复出初始数据。如图,具有加密算法的信道变成了如下形式:

在这里Alice提供密钥 $K_A$ 作为加密算法输入,生成密文;Bob提供密钥 $K_B$ 解密密文为明文。对称密钥系统下,Alice和Bob的密钥相同且保密;公钥系统下,使用一对密钥,其中一个为全世界所知,另一个只有Bob或Alice知道。
对称密钥密码体制
凯撒密码就是一个普通替换算法,将每个字母用该字母后第 k 个字母替换,允许回绕即可。例如,k=3,则明文中的字母“a”变为密文中的字母“d”,明文中的字母“b”变为密文中的字母“e”,以此类推,因此k值作为密钥。,因为密钥值只有25个,如果你知道是使用凯撒密码,那么用不了多久就可以破解它。
单码代替密码是凯撒密码的改进版,使用字母表中一个字母替换另一个字母,替换规则不按照规律进行,而是每个字母都有一个唯一的替换字母。这样,任何一个字母都可以用另一个字母替换,替换过程形成了加密明文的一种可行规则。
如下就是一个使用单码替换的密钥:

在这里密钥的情况将会出现 26! 种,暴力破解变得不可行。
当考虑Trudy破解Bob和Alice之间加密方案的难易程度时,可以根据入侵者所拥有的信息分为三种不同的情况。
- 唯密文攻击:通过大量统计密文的信息来破解明文的攻击方式。
- 已知明文攻击:攻击者通过某种手段获得了一对明文密文的匹配,此时如果我知道了
alice
所对应的密文,那么我密钥的爆破就确定了五位,26! 种的密钥下降到了 21! 种。 - 选择明文攻击:如果能使用加密系统,我们能选择合理的明文加密出对应的密文信息,对于单码替代密码来说,我只需要加密明文
abcdefghijklmnopqrstuvwxyz
观察输出即能确定所使用的密钥。对于高级复杂的密码,往往可能需要通过统计合适的明文-密文对才能推算出密钥。
多码替代密码举个例子就是使用两个不同的凯撒密钥,对于奇数位置,我取得第一个密钥作为结果,对于偶数位置我取得第二个密钥作为结果。

块密码
现代对称加密技术有两种宽泛的类型:流密码(stream cipher)和块密码(block cipher)。
在块密码中,要加密的报文被处理为 k 比特的块。例如,如果k=64,则报文被划分 为64比特的块,每块被独立加密。为了加密一个块,该密码采用了一对一映射,将 k 比特块的明文映射为 k 比特块的密文。
对于密钥复杂度来说,密钥复杂度与 k 的值有关,如果 k=3,那么下表会是其中一个可能的密钥:

对它们排列组合有一共有 8! 种密钥,对于现代计算机来说,这个很快就能计算完所有的结果。
全表块密码可以产生强大的对称密钥加密方案,但实现非常困难。例如,当k=64时,需要维护一张具有 $2^{64}$ 个输入值的表格,这几乎是不可能的任务。此外,如果Alice和Bob要更改密钥,他们将需要重新生成整个表格。因此,全表块密码提供了预先决定的输入和输出映射,这几乎是不可能实现的。
块密码使用函数模拟随机排列表,而不是使用全表。每个64比特的块被划分为 8 个 8 比特块,每个 8 比特块通过一个“8比特到8比特”表处理。这些输出块被重新装配成一个 64 比特的块,并回馈到输入,开始下一次循环。这种循环的目的是使得每个输入比特影响最后输出比特的大部分,块密码算法的密钥将是8张排列表。

目前比较流行的块密码有 DES,3DES,AES。DES使用了具有56比特密钥的64比特块。AES使用128比特块,能够使用128、192和256比特长的密钥进行操作。如果用1秒破解56比特DES的计算机(一秒破解 $2^{56}$个密钥)来破解一个128比特的AES密钥,要用大约149万亿年的时间才有可能成功。
密码块链接
对于块密码来说的确是比较安全的,但是弊端就是,对于相同的块,相同的密钥得到的必然是相同的结果。当攻击者看到相同的密文块时,它可能潜在地猜出其明文,并且通过识别相同的密文块和利用支撑协议结构的知识,甚至能够解密整个报文。
其中一种思路是在对明文块加密的时候,异或一个随机数,发送的时候将随机数一起发送,虽然随机数是明文发送,但是只要解不出明文,那么它获取的随机数也毫无意义。
引入随机性解决了一个问题而产生了另一个问题:Alice必 须传输以前两倍的比特。实际上,对每个加密比特,她现在必须再发送一个随机比特,使需要的带宽加倍。为了有效利用该技术,块密码通常使用了一种称为密码块链接(Cipher Block Chaining,CBC)的技术。其基本思想是仅随第一个报文发送一个随机值, 然后让发送方和接收方使用计算的编码块代替后继的随机数。
CBC的运行过程如下:
- 在加密报文(或数据流)之前,发送方生成一个随机的%比特串,称为初始向量(Initialization Vector,IV)。将该初始向量表示为c(0)。发送方以明文方式将IV发送给接收方。
- 对于第一个明文,我们先对它异或这个初始向量再进行加密,得到了密文c(1)。那么 c(1)将作为第二个密文的随机数与明文进行异或,以此类推。
当设计安全网络协议时,CBC有一种重要的后果:需要在协议中提供一种机制,以从发送方向接收方分发IV。
公开密钥加密
对称加密有一个最大的弊端是双方要先协商一个加密解密的密钥,并且确保该密钥不会被泄露。但是在计算机网络当中,通信的主体可以是任意两台主机,如果都要协商密钥那会是一个巨大的挑战。此时通信双方能够在没有预先商定的共享密钥的条件下进行加密通信吗?1976年, Diffie和Hellman论证了一个解决这个问题的算法(现在称为Diffie-Hellman 密钥交换)。公开密钥密码系统也有许多很好的特性,使得它不仅可 以用于加密,还可以用于鉴别和数字签名。
公开密钥密码的使用在概念上相当简单。假设Alice要和Bob通信,而Bob ( Alice报文的接收方)则有两个密钥,一个是世界上任何人(包括入侵者Trudy)都可得到的公钥 (public key),另一个是只有Bob知道的私钥(private key) 。

Alice 使用公钥加密之后,发送密文,Bob收到密文之后使用私钥解密得到明文。
因此公开密钥密码体制的使用在概念上是简单的。但是有两点必须要注意:
- 首先应关注的是,尽管入侵者截取到Alice的加密报文时看到的只是乱码,但是入侵者知道公钥 (显然Bob的公钥是全世界都可以使用的)和Alice加密所用的算法。Trudy可以据此发起选择明文攻击,使用已知的标准加密算法和Bob的公开可用的加密密钥对她所选择的任意报文编码!
- 在单一共享密钥情况下,可以确定一点:能够正确解密我加密的信息的人一定拥有密钥,那么与它通话便间接地认证了身份。但是公钥加密体制下,这一点行不通了,因为所有人都知道我的公钥,这就需要用数字签名把发送方和报文绑定起来。
RSA加密
RSA几乎是现在用的最多的公开密钥的加密算法了,关于它的加密解密,密钥分发,原理性验证等内容在我的另一篇blog详细写到了。
会话密钥
因为RSA可加密的长度受限于密钥长度,如果要发送的信息很长,那么RSA显然不是一个很好的选择,并且算法复杂度来看,RSA的效率比常规的对称加密算法慢很多,时间大概是100倍到1000倍左右。
因此我们可以选择使用 RSA 先交换一个对称加密的密钥,后续的通信以这个密钥进行加密即可,那么协商的这个密钥就叫会话密钥(session key)。
RSA的工作原理
报文完整性和数字签名
报文完整性也称为报文鉴别,连同报文完整性,我们主要讨论两个话题,一个是数字签名,一个是端点鉴别。当Bob收到一个自称是 Alice 发送的报文时,为了鉴别报文,Bob需要证实:
- 该报文的确源自Alice
- 该报文在到Bob的途中没有被篡改。
报文完整性这个问题在所有安全网络协议中都是至关重要的。
密码散列函数
对于这个函数我们有如下要求:
- 散列函数以任意长度字符串 m 为输入,并计算得到一个称为散列的固定长度的字符串H(m)。因特网检验和和CRC均具有这个特性。
- 找到任意两个不同的报文咒和y使得H(x)=H(y),在计算上是不可能的。
而因特网检验和并不符合这个特点,如图:

而比较复杂的信息摘要算——md4,md5,SHA(Security Hash Algorithm)系列则能很好的满足这个特性。
报文鉴别码(MAC)
来看一下将如何执行报文完整性:
- Alice生成报文 m 并计算散列H(m),这个H(m)就被称为报文鉴别码(MAC)
- 然后Alice将H(m)附加到报文m上,生成一个扩展报文,并将该扩展报文发给Bob。
- Bob接收到一个扩展报文(m,h)并计算H(m) 。如果H(m) = h,Bob得到结论:一切正常。
但是事实上,如果Trudy知道了他们的协商,那么它可以伪造一份报文 m’,并使用 hash 生成 H(m’),对于Bob来说,验证也能通过。那么此时就需要双方共享一个秘密 s,这个 s 是一个比特串,被称为鉴别密钥。生成hash的时候额外附加上一个 s 进行,即附加的消息变成 H(m+s),这样,不知道 s 的攻击者一定无法伪造任何消息发送。
数字签名
在数字领域,人们通常需要指出一个文件的所有者或创作者,或者表明某人认可一个文件内容。数字签名(digital signature)就是一种在数字领域实现这些目标的密码技术。
正如手工签字一样,数字签名也应当以可鉴别的、不可伪造的方式进行。这就是说,必须能够证明由某个人在一个文件上的签名确实是由该人签署的(该签名必须是可证实的),且只有那个人能够签署那个文件(无法伪造)。
来考虑这样一个问题,在某些时候说话你需要证明某人确实说过这个话,最好的办法是录音,但是录音是可以伪造的,并且一般我们认为口头说是无效的,那么第二我们可能会考虑到签一份合同,签上自己的名字,证明我说过这话。同样,数字签名也是如此,如果我要签一个合同,我可以直接把合同的内容使用我的私钥加密公布出去表示我签署了这个合同。

如果其它人想要证明这个合同确实被我签署过了,可以拿出我公布的签名,使用我公布的公钥进行解密,解密出来与合同的结果一致,则说明此份合同确实被我签署过。因为只有 Bob 拥有私钥,因此只有它能签署这个合同(无法伪造),而一旦签署了这个合同,任何人通过他公布的公钥都可以对这份合同进行验证,确保它不可抵赖(可证实)。
注意到下列问题是重要的:如果源文档 m 被修改过,比如改成了另一个文档 m’,则 Bob 对 m 生成的签名对 m’ 无效,因为对签名进行公钥解密之后的内容肯定不等于m’,因此数据签名可以提供完整性。
而前面说过了,RSA 可加密的位数取决于密钥的长度,通常 RSA 的密钥长度为 2048 位,也就是一百多个字节。而一份合同的文本通常多达几百上千字,此时我们可以采取这样一种方式:对签署的文档进行散列,散列成固定长度的数据,在对散列数据进行私钥加密即可。验证的时候只需要验证给定合同的散列值是否等于用公钥解密出来的散列值即可,一致则证明对方确实对这份文档签署过。

公钥认证
有一个可信第三方认证中心(Certification Authority,CA)对用户的密钥进行绑定,CA 的职责就是使识别和发行证书合法化,这样的话可以避免其他人以自己的身份自称。
报文完整性和真实性算法算法也叫MAC(Message Authentication Code)算法。
端点鉴别
端点鉴别(end-point authentication)就是一个实体经过计算机网络向另一个实体证明其身份的过程,例如一个人向某个电子邮件服务器证明其身份。
接下来我们来一步一步设计鉴别协议。
鉴别协议ap1.0
我们能够想象到的最简单的鉴别协议就是打招呼,自报家门,如下图所示:

这个协议的缺陷是明显的,即Bob无法判断发送报文是否真实,是否为本人所发,因为任何一个人都可以发送这个报文。
鉴别协议ap2.0
第二种端点鉴别协议就是使用 IP 地址鉴别。这可能阻止对网络一无所知的人假冒Alice 但是无法阻止对本书具有深入学习的人,因为如果我们可以构建一个操作系统生成一个IP数据报,并在IP数据报中填入我们希望的任意源地 址(比如Alice的周知IP地址),再通过链路层协议把生成的数据报发送到第一跳路由器。此后,具有不正确源地址的数据报就会忠实地向Bob转发,如下图所示:

这事IP哄骗的一种形式。如果Trudy的第一 跳路由器被设置为只转发包含Trudy的IP源地址的数据报,就可以避免IP哄骗。
鉴别协议ap3.0
进行鉴别的一种经典方法是使用口令,也就是我们俗称的密码。如果在交互的时候携带口令,对方便可以验证口令是否正确来判定对方的身份,但是它可能依旧不安全,来看下面的一个情景:

口令如果明文传输,那么很有可能被窃听到,于是之后窃听者 Trudy 可以以相同的口令对 Bob 发起会话,同样能够通过验证身份。
鉴别协议ap3.1
这个版本要求双方有一个共享密钥,然后用共享密钥去加密口令传输,但是并没有明显的改观,因为Trudy依然可以窃听到口令的加密版本然后直接发送。
鉴别协议ap4.0
在这个版本中对通话引入“时间戳”校验了,当然不能直接发送这个时间戳,而是需要使用密钥加密时间戳,这事一个比较巧妙的思路,当然这里不一定是加密时间戳,可以加密一个不重数,不重数(nonce)是在一个协议的生存期中只使用一次的数。
鉴别思路变成了下面的形式:

其实跟ssh的公钥登录有异曲同工之妙,如何验证你是该密钥的拥有者呢?只需要我使用服务器上的公钥加密一串随机数给客户端,如果客户端能使用本地的私钥对该数据进行解密并将随机字符串返回给服务端,服务端验证通过之后便能确定你的身份是合法的,并返回一个 shell 给你的 ssh 客户端。
安全电子邮件
安全性主要是指信息不会被窃取。为因特网协议栈上面4层的任一层提供安全性服务是可能的,其中一层能提供安全性保证之后,所有使用这一层的上层协议均能得到保证。
比如链路层协议是提供安全性保证的,那么使用该链路层协议的所有协议都可以得到安全性保证,如果是网络层提供安全性,那么所有使用这个网络层协议的协议都可以得到安全性保证。和之前一样,IP 不提供可靠性保证,但是 TCP 提供,所以使用TCP套接字的应用都有可靠性保证,而 UDP 则没有可靠性保证。和我之前想的一样,如果这一层不提供这个功能,那便只能是应用层在设计协议的时候自己去实现这个功能。
举个很简单的例子,你不希望你的程序有拥塞控制,且可靠,那么你就不能使用 TCP,因为使用TCP一定会有拥塞控制,这个不管在应用层怎么实现都逃不掉的。因此你只能选择 UDP,但是它不可靠你就需要在应用层去实现诸如重传等机制,来让你基于 UDP 的应用层协议变得可靠。
接下来会介绍具有安全性的协议,分别是安全电子邮件协议(应用层),SSL(传输层),IPSec(网络层),IEEE 802.11无线局域网协议(链路层)。
虽然在较低层部署安全协议可以给几乎所有协议提供安全性,但是一定会有的一个问题是:较低层部署的协议难以很快的同步,并且如果链路层部署安全协议仅仅意味着链路层数据加密,当数据递交到网络层的时候数据是不加密的,意味着传输过程中实现了网络层的中间设备能窃取到明文信息。如果网络层是加密的,意味着递交到传输层是不加密的,在主机上我如果获取了读取操作系统套接字接口的权限那么所有的数据都将很危险。
因此在上层实现协议的安全性也是很有必要的,在应用层,一个很典型的安全协议就是 PGP(Pretty Good Privacy)。
安全电子邮件协议
我们首先考虑一下安全的电子邮件协议应该具备什么样的特点。重中之重是机密性,即,即使通信线路随时会被窃听,但是依然只有双方知道他们所交流的内容。第二种特性是具备发送方鉴别,电子邮件应当具备端到端的鉴别特性,并不是任何一个人都可以伪装成 Bob 给 Alice 发送信息。
先来讨论第一个问题,即报文机密性,最简单的是使用 DES 或者 AES 加密,如果对称密钥足够长,且仅有Alice和Bob拥有该密钥,则其他人(包括 Trudy)要想读懂这条报文极为困难。但是密钥分发会极为困难,因为要求他们事先得知其他人都不知道的消息,而对于网络环境来说这很难做到,那么就可以考虑使用 RSA 来进行报文的加密,如之前所提到的,RSA 加密效率非常低,所以可以使用 RSA 交换一个 AES key,然后后续对话使用 AES 加密,这个机密性的问题就解决了。
就像下面这样:

下面是符号的解释:
- $m$:明文信息
- $K_s$ :会话密钥
- $K^+_B$:Bob的公钥
- $K^-_B$:Bob的私钥
第二个关注的特性就是其他人可以伪造 Bob 的身份来与 Alice 通信,比如 Trudy 发送自己的公钥给 Alice,这样会导致 Alice 一直在和 Trudy 通信,身份的真实性无法保证。
为了解决这个问题,我们需要有一个可信的第三方,也就是 CA(证书机构)保存用户的公钥,那么在验证的时候我如果不信我就可以去查 CA,来看看这个用户的公钥是否正确。
PGP
PGP软件的不同版本使用MD5或使用SHA 来计算报文摘要;使用CAST、三重DES或IDEA进行对称密钥加密;使用RSA进行公开密钥加密。
安装PGP时,软件为用户产生一个公开密钥对。该公钥能被张贴到用户的网站上或放置在某台公钥服务器上。私钥则使用用 户口令进行保护。用户每次访问私钥 时都要输入这个口令。PGP允许用户选择是否对报文进行数字签名、加密报文,或同时进行数字签名和加密。
如图是一个签名过的 PGP 报文:

如图是一个加密过的 PGP 报文:

此外,PGP允许Alice为她所信任的用户鉴别更多密钥提供担保。一些PGP用户通过保持密钥签署方(key-signing party)互相签署对方的密钥。用户实际走到一起,交换公钥,并用自己的私钥对对方的公钥签名来互相验证密钥。
使TCP连接安全:SSL
通过使用密码技术我们可以加强 TCP 协议的安全性。TCP的这种强化版本通常被称为安全套接字层(Secure Socket Layer, SSL)。SSL版本 3 的一个稍加修改的版本被称为运输层安全性(Transport Layer Security,TLS)
SSL得到了所有流行Web浏览器和Web服务器的支持,并基本上被用于所有因特网商业站。https
就是指 HTTP协议+SSL协议的协议栈。
考虑一个场景:Bob通过信用卡支付,在Alice的网站上购买东西,钱到,Alice 发货,一切听起来合乎常理,但是如果不采取安全措施可能就会有些意外:
- 如果没有机密性,那么Trudy可以轻松获取到Bob的银行卡信息并以它的身份为自己购买东西。
- 如果没有使用完整性,那么Trudy可能可以修改Bob的订单,使得它购买自己本不想购买的东西。
- 如果没有使用端点鉴别,那么Bob可能访问Trudy的一个网站而不是Alice的,或者Trudy能够假冒Bob的身份到Alice 的网站上购买东西。
SSL通过采用机密性、数据完整性、服务器鉴别和客户鉴别来强化TCP,就可以解决这些问题。

SSL可以看成是一个运输层协议。
具体描述
SSL握手
这个过程步骤如下:
- 客户发送它支持的密码算法的列表,连同一个客户的不重数,发送Client Hello消息。
- 服务器从该算法列表中,选择一个对称密钥算法和一个非对称密钥算法还有一个 MAC 算法,还有服务器证书和服务器不重数,发送Server Hello消息,连同选择的算法一起。
- 客户端会验证该证书是否真实来自该网站的,有无过期,是否被撤回,并查看签名看看消息是否有被篡改,如果没问题的话,会从证书中提取出服务器的公钥,用于等会加密,那么客户端随机生成一个前主密钥(Pre-Master Secret,PMS),使用服务器公钥进行加密发送。同时,它自己也会根据不重数去计算主密钥(Master Secret,MS),这里计算不重数应该是把服务端和客户端的两个数进行某个运算去得到的。
- 服务器收到之后,使用自己的私钥解密得到前主密钥,同时,它有了两个不重数和前主密钥,它也可以算出来主密钥。主密钥有四个内容:客户端session key,服务端session key,Client MAC key,Server MAC key。它们双方都掌握了这四个密钥,它们用自己的密钥加密信息和MAC,用对方的密钥解密自己收到的加密信息和MAC。
- 服务端此时用 Server session key 加密发送 “Server Finished” 消息,并且还会发送一个总消息的 MAC(使用 Server MAC key加密它所发送的总消息的 hash)。
- 客户端收到该消息使用 Server session key 解密发现是 “Server Finshed”,它可以用 Server MAC key解密收到的MAC,和之前服务器发给它的所有包,看看是否具有完整性,hash 是否一致。
- 检测完整性之后,它也用Client session key加密一个 “Client Finished” 的消息,同样也会包含关于自己发送的所有消息的MAC(也是对自己发送的所有消息进行一次Hash之后用Client MAC key加密发送)。
- 同样,服务端也会去验证,收到的消息,使用 Client session key去解密,然后把收到的所有内容 hash 之后用 Client MAC key解密一下对面发的 MAC,看看 hash 是否一致,检查完整性。
- 这样整个握手过程就算是完成了,后续的会话内容都会加密和鉴别。
以上的步骤完美符合了机密性,可鉴别性和完整性,能够做到真正意义上的安全。
不重数用于防止重放包攻击,因为密钥是会通过前主密钥和不重数计算的,就算重放包导致了客户端生成前主密钥一样,客户端不重数一样,那么服务端不重数不一样它最后的 session key 和 MAC key 都会不一样,握手阶段就无法通过完整性检查。
连接关闭
一般来说,可以直接发送一个 TCP FIN 报文结束,但是这种设计为为截断攻击(truncation attack)创造了条件,Trudy再一次介入一 个进行中的SSL会话中,并用TCP FIN过早地结束了该会话。如果Trudy这样做的话,Alice将会认为她收到了 Bob的所有数据,而实际上她仅收到了其中的一部分。
这个问题的解决方法就是在类型字段中指出该记录是否为终止 SSL 会话使用的,如果说它在收到关闭 SSL 之前收到了一个 TCP FIN 报文,那么服务端就会认为有坏东西在耍花招,便可以不必理会。
网络层安全性:IPsec和虚拟专用网
IP安全(IP Security)协议更常被称为IPsec,它为网络层提供了安全性。IPsec为任意两个网络层实体(包括主机和路由器)之间的IP数据报提供了安全。
使用IPsec,可以创建了运行在公共因特网之上的虚拟专用网(Virtual Private Network,VPN)。
IPsec 可以加密它发送给接收实体的所有数据报的载荷,它可以是 TCP,UDP 或者是 ICMP 报文。因为几乎所有因特网的主机都实现了 TCP/IP,所有的路由器都实现了 IP 协议,因此我们说在 IP 层提供安全性服务是地毯式的覆盖。
IPsec提供了机密性、源鉴别、数据完整性和重放攻击防护。
IPsec和VPN
当我们需要通过公共因特网访问自己的一个独立IP网络时,就需要用到VPN,如图所示:

AH协议和ESP协议
在IPsec协议族中,有两个主要协议:鉴别首部(Autlientication Header,AH)协议和封装安全性载荷(Encapsulation Security Payload,ESP)协议。
AH协议提供源鉴别和数据完整性服务,ESP协议提供了源鉴别、数据完整性和机密性服务。
安全关联
在从源实体向目的实体发送IPsec数据报之前,源和目的实体创建了一个网络层的逻辑连接。这个逻辑连接称为安全关联(Security Association,SA),一个 SA是一个单工逻辑连接。
注意到,如果 VPN 内部的主机要对外访问公网服务器,那么应该是发送 IPv4 数据报而不是 IPsec 数据报。
在VPN中,网关路由器会维护自己到 VPN 网络层设备的所有 SA,如果两个VPN要通过公网连接,则它们也会维护一个 SA,如下面的例子:

在路由器 R1 中,会维护有关该 SA 的所有信息,包括:
- SA的32比特的标识符,称为安全参数索引(Security Parameter Index,SPI)
- SA的初始接口和目的接口
- 将使用的加密类型
- 密钥
- 完整性检查的类型
- 鉴别密钥
IPsec数据报
IPsec有两种不同的分组 形式,一种用于所谓隧道模式(tunnel mode ),另一种用于所谓运输模式(transport mode),我们主要关心隧道模式。
假设路由器R1接收到一个来自主机172. 16. 1. 17 的普通IPv4数据报,该分组的目的地是主机172. 16. 2. 48。R1收到这样的数据报之后会发生如下的事件,将该普通的IPv4数据报转换为IPsec数据报。
- 在初始IPv4数据报(它包括初始首部字段!)后面附上一个“ESP尾部”字段。
- 使用算法和由SA规定的密钥加密该结果。
- 在这个加密量的前面附加上一个称为“ESP首部”的字段,得到的包称为 enchilada。
- 使用算法和由SA规定的密钥生成一个覆盖整个 enchilada 的鉴别 MAC。
- 该MAC 附加到 enchilada 后面形成荷载。
- 最后生成一个新的 IPv4 首部,上面的所有包作为 payload。
就像下面这张图一样:

此外,这里新 IP 的首部中协议字段会被设置为 50 表明这是一个使用 ESP 协议的 IPsec 数据报。
IPsec 服务小结
我们以攻击者视角来说。第一,Trudy不知道SA所使用的鉴别密钥和加密密钥,那么它不能够解得 IPsec 数据报的内容。也看不到这个IPsec数据报真实使用的上层协议,源地址和目的地址,因此这种机密性比SSL范围更为宽广。
第二,当Trudy试图篡改数据包的时候,它将很难通过完整性检查。
第三,它如果想伪造其中一个路由器的源地址,它也不能通过完整性检查。
最后,IPsec包含序号,这使得它将无法重放攻击。
IPsec在任何通过网络层处理分组的设备对之间,提供了机密性、源鉴别、数据完整性和重放攻击防护。
IPsec中的密钥管理
mark一下,以后来看。
使无线LAN安全
mark一下,以后再说。
运行安全性:防火墙和入侵检测系统
现在我们已经看出来了一点:因特网不是一个很安全的地方。在计算机网络中,当通信流量进入/离开网络时要执行安全检查、做记录、丢弃或转发,这些工作都由被称为防火墙、入侵检测系统(IDS)和入侵防止系统(IPS)的运行设备来完成。
防火墙
防火墙具有3个目标:
- 从外部到内部和从内部到外部的所有流量都通过防火墙。
- 仅被授权的流量(由本地安全策略定义)允许通过。
- 防火墙自身免于渗透。
Cisco和Check Point是当今两个领先的防火墙厂商,Linux 中 iptables 的合理配置也可以产生一个防火墙,防火墙现在经常在路由器中实现并使用SDN进行远程控制。
防火墙能够分为3类:传统分组过滤器(traditional packet filter)、状态过滤器 (stateful filter)和应用程序网关(application gateway)。
传统的分组过滤器
通常一个机构要搭建能访问因特网的网络,需要连接 ISP 提供的网关路由器,所有要去因特网的流量都会经过网关路由器而这个路由器正是分组过滤(packet filtering)出现的地方。分组过滤器独立地检查每个数据报,然后基于管理员特定的规则决定该数据报应当允许通过还是应当丢弃。通常基于以下因素:
- IP源或目的地址。
- 在1P数据报中的协议类型字段:TCP、UDP、ICMP、OSPF等。
- TCP或UDP的源和目的端口。
- TCP标志比特:SYN、ACK等。
- ICMP报文类型。
- 数据报离开和进入网络的不同规则。
- 对不同路由器接口的不同规则。
比如一个机构他只希望自己的公共web服务器被访问而不接受其它 TCP 的syn报文那就阻挡 syn 报文目的端口非 80 的进报文段。如果该机构不希望它的内部网络被外部绘制结构图(被跟踪路由),那么它能够阻挡所有ICMP TTL过期的报文离开该机构的网络。因为 traceroute 本质就是发送 TTL = 1 ~ 255 的一个过程去跟踪的路由,设TTL的值为 i 在此过程中,它的第 i 跳路由会通过ICMP发送 TTL 过期报文给我们的主机。
如下是某服务器的过滤规则:

这里对 smurf 进行了一个了解。smurf Dos 攻击是一种 DDOS 攻击,结合使用 IP 欺骗的方式。发包的时候,把一目的地址设为广播地址,把源地址设为我要攻击的目标地址。这样路由器转发这个分组的时候,网络中大量主机会响应 ICMP echo request给被攻击的地址,导致被攻击的主机被淹没,无法接收正常的流量。
过滤也可以根据 TCP ACK 比特是否设置来进行,如果我们要阻止外对内发起 TCP 连接,我们就丢弃 TCP ACK=0 的入分组(因为 TCP 规定握手中的第一步 ACK 必须设置为 0,剩下的所有 TCP 分组 ACK 设置为1)。

第一个规则,允许了内部用户发送 TCP 连接,且目的端口为 80 的分组。
第二个规则,允许了外部源端口为 80 的分组,且ACK要置为1,即不能是这个80端口主动发起连接访问的。
这两个规则允许了内部用户访问外部的 web 服务器。
第三个规则,允许了内部用户发送 UDP 且目的端口 53 的分组。
第四个规则,允许了外部服务器发送源端口为 53 的UDP分组
这两个规则允许了内部用户使用外部 DNS 服务器的域名解析功能。
状态分组过滤器
虽然这样可以基本达到所说的目的,但是,攻击者可以构造任意的包来绕过防火墙规则,比如说,它构造一个 源端口为 80 ,ack=1 的大量包,将能一一通过防火墙的规则,并且这样的分组很有可能导致内部系统崩溃。如果要解决这个问题我们显然可以阻挡 ack 分组,但是这样将使得内部用户无法收到来自正常 web 服务器的内容。
状态过滤器通过用一张连接表来跟踪所有进行中的TCP连接来解决这个问题。因为防火墙能够通过观察三次握手(SYN、SYNACK和ACK)来观察一条新连接的开始;而且当它看到该连接的一个FIN分组时,它能够观察该连接的结束。 当防火墙经过比如说60秒还没有看到该连接的任何活动性,它也能够假设该连接结束了。
如下两张表是状态分组过滤防火墙的一个访问控制列表和连接状态表:

如果再像之前那样的方式,去构造一个包,源端口为 80,目的端口为其它任意,ACK=1。那么匹配到了表中第二条规则,发现在允许进入之前需要核对连接表,于是进行查找,发现没有这样的一条连接,于是选择丢弃。
应用程序网关
如果我仅仅需要一个合法的用户才能向外发起 Telnet 连接的话,这就不能使用之前两种类型的防火墙了,因为用户身份不存在于 IP 或者 TCP 首部当中,而是存在于应用层数据当中,这个时候就需要应用程序网关型防火墙发挥作用了。
那么我现在路由器配置不允许 Telnet 请求,仅仅允许一个指定服务器发起 Telnet 请求,那么如果要使用 Telnet 则必须先登录该应用程序网关,输入用户名密码之后检测你是否处于合法用户的范围内,如果是那么再让你输入 IP,用户,密码,该应用程序网关会代你执行 Telnet,并中继所有数据。
应用程序网关也有其缺陷。首先,每一个应用程序都需要一个不同的应用程序网关。 第二,因为所有数据都由网关转发,付出的性能负担较重。当多个用户或应用程序使用同一个网关计算机时,这成为特别值得关注的问题。最后,当用户发起一个请求时,客户软件必须知道如何联系这个网关,并且必须告诉应用程序网关如何连接到哪个外部服务器。
入侵检测系统
显然,防火墙并不能真的阻挡恶意攻击,因为恶意代码很有可能在应用层,而应用程序网关防火墙虽然能做,但是显然它仅仅只能针对一个应用程序的分组。
显然,这为另一种设备提供了商机,这种设别能够识别应用层数据,拦截或对网络管理员告警。
当观察到潜在恶意流量时能产生告警的设备称为入侵检测系统(Intrusion Detection System,IDS)
滤除可疑流量的设备 称为入侵防止系统(Intrusion Prevention System,IPS)
IDS系统大致可分类为基于特征的系统(signature-based system)或基于异常的系统 (anomaly-based system)。
基于特征 IDS 会嗅探每一个分组,如果分组与特征数据库匹配上了,那么就会产生告警。它的缺点也比较明显,对于新型攻击无法及时响应。
目前大部分部署的 IDS 都是基于特征的。
Snort是一个比较著名的开源IDS,通过该应用程序,网络管理员可以根据自己的需求编写规则,通过修改现有特征或新建一个特征。
小结
主要深入学习了密码学的相关知识,认识了端点鉴别,完整性检查等具体方法。以及对SSL协议的实现有了较为深入的了解,对VPN也有了一定的了解。网络安全这一章也是终于结束了,我对这本书大概到此为止了,虽然后面那一章还有流媒体相关的知识点,但是还是乖乖背八股吧,不要再花过多的时间了。。