TCP/IP 笔记 - 安全

时间:2022-11-26 20:29:25

安全:可扩展身份认证协议、IP安全协议、传输层安全、DNS安全、域名密钥识别邮件

任何由用户或以用户账号执行却违背了用户本身意愿的软件被称为恶意软件

网络安全是一门十分广泛及有深度的学识,而本书旨在了解TCP/IP协议族知识,所以书中只介绍了一些TCP/IP所使用的部分安全方案。并且对安全这块我也没多少深入的研究,也就基于书本内容做些知识摘抄以供了解和学习。

信息安全基础

从信息安全的角度看,无论是否在计算机网络中,信息都该具有一些属性:

  1. 机密性,信息只能为其指定的用户知晓。

  2. 完整性,信息在传输完成之前不能够通过未授权的方式修改。

  3. 可用性,在需要的使用信息是可用的。

  4. 可认证性,一个经过身份认证的组织或个体是不能够被其他个体假冒的。

  5. 不可抵赖性,一个个体做出的任何行为都能够在此之后得到证实。

  6. 可审计性,一些可信的日志或说明能够面试信息使用的过程。

前三者是重要的核心属性,又称'CIA三元组'。

根据[VK83],攻击通常被分为被动和主动两类。被动攻击一般会监视或窃听网络流量的内容,如果不加以控制,它将会导致信息未经授权就发布出去,这破坏了信息的机密性。主动攻击一般会篡改信息或使其拒绝服务,这破坏了信息的完整性和可用性。

被动攻击:

  窃听(机密性)

  流量分析(机密性)

主动攻击:

  消息流篡改(可认证性,完整性)

  拒绝服务DoS(可用性)

  伪造机构(可认证性)

通过加密机制,即可满足以上两种攻击的防御需求,通过加密后的数据不容易泄露信息内容、不容易破坏其完整性、也更安全的保障了可认证性。

基础的加密和相关知识

传统的基础加密主要用于保护信息的机密性,但其他属性如完整性和可认证性也能够借助加密以及相关的数学技术达到。下面的图说明了两个重要的加密算法:对称密钥和公开(非对称)密钥是如何工作的。

TCP/IP 笔记 - 安全

在对称密码系统中,由于加解密的算法相同,它们的密钥也是相同的。

在非对称密码系统中,每一个个体都拥有一对密钥,包括一个公钥和一个私钥。公钥是公开的,任何希望向这对私钥所有者发送消息的人都能够获得。公钥和私钥有数学上的关联,它们都是密钥生成算法的输出结果。如果不知道对称密码系统中的对称密钥或非对称密码系统中的私钥,任何第三方截获密文后都无法生成相应的明文。

对称密码算法通常被分为分组密码(或称块密码)与流密码两类。分组密码每次只对固定数目的比特块进行操作,而流密码将提供的大量比特作为输入并且会持续的运行下去。多年来流行的对称密码算法是数据加密标准(DES,是一种分组密码,使用64比特的数据块与56位的密钥)。该算法最终被认为不安全,后期采用3重DES利用两个或三个不同密钥对每一个数据块进行三次DES加密。但无论DES还是3DES,现在都逐渐被高级加密标准(AES)所取代[FIPS197]。AES针对不同版本所提供的密钥长度,如128位、192位、256位,于是就有了AES-128、AES-192、AES-256。

如上图,非对称密码算法存在一个问题:发送者使用接收者的公钥进行消息加密后发给接收者,那么只能拥有接收者私钥才能够对消息进行解密,然而这个消息不能保证是真实可靠的(因为任何人都能够发送这条消息给接收者)。于是基于非对称加密的公钥-密钥的关联性,非对称密码系统提供了另一项功能:对发送者进行认证。
该功能由将公钥加密和私钥解密反向操作而实现,如下图:

TCP/IP 笔记 - 安全

流行的公钥密码算法如RSA,在其初始化阶段,需要生成两个大素数p和q。这项工作首先需要随机地生成数值较大的奇数,后检验这些数是否为素数,直到找到两个大素数为止。两个素数的乘积 n = pq 被称为模。n,p,q的长度一般用比特来衡量。推荐n采用2048比特的长度,但通常情况下n为1024比特,p和q的长度为512比特。

根据RSA算法,n的构建方法为:

    Φ(n) = (q - 1)(p - 1)

Φ(n)的值表示n的欧拉数,是那些比n小且与n互质的正整数的个数。

根据Φ(n)的定义,选择RSA的公钥指数(称为e,表示加密),并按照关系式d = e(^-1)(modΦ(n))得到私钥指数(称为d,表示解密)作为乘法逆元素。为获取密文c,需要使用公式m = m(^e)(mod n)对明文m进行计算;反之则需要公式m = c(^d)(mod n)进行解密。一个RSA的公钥包含公钥指数e和模n,对应的私有则包含私钥指数d和模n。如果为了对一条消息m进行RSA数字签名,可以通过公式s = m(^d)(mod n)计算s的数值作为m的签名。任何接收到s的人能够使用公有元素e与公式m = s(^e)(mod n)进行检验,这样就能够验证生成数值s的是RSA的私有值d。RSA的安全性是基于对大数分解因数的困难性。

Diffie-Hellman-Merkle 密钥协商协议(DH)提供了一种解决"通信双方如何在窃听者不知情的情况下完成共同密钥协商"的计算方法,DH技术已用于许多与互联网相关的安全协议[RFC2631]。

DH的工作如下描述:

  1. 假设所有人都有相同的特征,并且知道两个证书p和q。p是一个(大)素数,g是模p的原根(g<p)。

  2. 基于1,集合Z(_p) = {1,...,p-1}中的每一个整数都能够通过不断地增加g来生成,也就是说对于任意一个证书n,必定存在倍数k使式子g(^k) ≡ n(mod p)成立。在给定g、n与p的情况下寻找合适的k值被认为是一件困难的事(离散对数问题),在给定g、k与p的情况下找出n是容易的。

建立一个共享的安全密钥过程如下(A和B之间):

  1. A选择一个秘密的随机数a,并按照公式 A = g(^a)(mod p)计算出A的值,然后将这个值发送给B;B选择一个秘密的随机数b,并按照公式 B = g(^b)(mod p)计算出B的值,然后将这个值发送给A。

  2. A将按照以下公式计算K值:K = B(^a)(mod p) = g(^ba)(mod p);B将按照以下公式计算K值:K = A(^b)(mod p) = g(^ab)(mod p)。

由于g(^ab)和g(^ba)是相等的,所以A和B都能获得协商密钥K。第三方窃听者只能获取g、p、A、B,因此在解决离散对数问题之前将无法获取密钥K。

在通信双方需要交换多条消息的场景中,通常会建立一个短期的会话密钥来进行对称加密。会话密钥一般由密钥派生函数(KDF)根据一些输入而生成的随机数,这些输入可能是一个主密钥或之前的会话密钥。如果一个密钥被破解,那么由该密钥加密的任何数据都会被破解,然而在一个持续的通信会话期间,往往会多次更改密钥。如果一种方案能够保证即使有一个会话密钥被破解而由其他密钥加密的后续通信过程仍然安全,那么就称该方案是完全正向保密(PFS)的。通常情况下能够提供完全正向保密的方案需要额外的密钥交换与认证过程,这样就引入了新的开销。

加密随机数是在密码协议中只使用一次的数值(又称临时密钥)。常用于认证协议,选择一个随机数或者伪随机数来保障时新性(时新性要求选取最新发生的消息或操作)。例如,在一个challenge-response协议中,服务器会为请求的客户端提供一个临时密钥,而客户端需要在指定时间内发送认证资料与临时密钥的副本作为响应。由于重放到服务器上的旧的认证交换信息不会包含正确的临时密钥数值,因此这种方法能够避免重放攻击。

混淆值是一个用于加密文本中的随机数或者伪随机数,可用于防御对密文的蛮力攻击(反复地猜测密码、口令、密钥或等效的秘密中并验证其是否正确)。

加密散列函数,类似于部分加密算法,用于做传输数据完整性的保障及预防对消息的篡改攻击。当一条消息M作为输入时,加密散列函数的输出H被称为这条消息的摘要或指纹H(M)。它不仅易于计算,还具有以下特征:

  1. 原像不可计算性,在给定摘要H(M)而未知消息M的情况下,难以得出消息M的值。

  2. 原像不相同性,给定消息M1的摘要H(M1),找出消息M2(M1 ≠ M2)使它的摘要与M1的摘要相等(H(M1) = H(M2))是十分困难的。

  3. 抗碰撞性,找出一堆摘要相同(H(M1) = H(M2))而自身不同的消息M1、M2(M1 ≠ M2)是十分困难的。

目前最通用的两个加密散列算法是生成128位摘要的消息摘要算法(MD5)和生成160位摘要的安全散列算法(SHA-1)。SHA-2基于一系列SHA函数,能够生成长度224,256,384,512位的摘要。

消息认证码(简称MAC或MIC),一般基于有密钥的加密散列函数,用于保障消息的完整性和防止各种伪造。这些函数类似于消息摘要算法,但需要一个私钥来验证消息的完整性,甚至也可能用于验证消息的发送者。给定有密钥的散列函数H(M,K),M为输入的消息,K是密钥,抵御"选择性伪造"意味着地方在不知道密钥K的情况下对指定的消息M生成散列值H(M,K)是非常困难的。消息认证码由于不止有一方知道对应的密钥,所以并不能为不可否认性提供坚实基础。

一个标准的使用加密散列函数的消息认证码被称为基于有密钥散列的消息认证码(HMAC),下面的公式定义了使用密钥K对消息M用H进行散列的方法(HMAC-H),它形成t字节的HMAC:

    HMAC-H(K,M)(^t) = Λ(_t)(H((K ⊕ opad) || H((K ⊕ ipad) || M)))

opad(外填充)是一个将数值0x5C重复|K|次的数组,ipad(内填充)是讲数值0x36重复|K|次的数组。⊕是向量的异或运算符,||是连接运算符,Λ(_t)表示取消息M最左边的t字节。其中的将一个散列函数作用于另一个散列函数的结构能够抵御所谓的扩展攻击,内填充与外填充的数值并不重要,但生成的2次密钥K1与K2需要有较大的区别。

随着消息认证码多年以来的发展,一些其他形式的消息认证码已经被标准化,比如基于密码的消息认证码CMAC、GMAC。这些新标准不使用HMAC的加密散列函数,而是使用分组密码,如AES。根据[RFC4493]描述,CMAC使用的是AES-128算法。GMAC则采用了AES算发的一种特殊模式,称为Galois/计数器模式,它仍然使用一个有密钥的散列函数(GHASH,并不是一个加密散列函数)。

证书相关知识

一种被称为"信任网络"的模型:通过一些当前用户(称为代言人)来做代言的方式以证明一个证书(身份-公钥对)的可靠性。一个代言人会对一个证书进行签名,然后将其发布出去,随着时间推移,如果一个证书有越来越多的代言人,那么它就越可靠。该模型是分散的、没有中心的权威机构,因此它具有一定的"草根"性。"信任网络"的优缺点显而易见,有点是其不存在中心的权威机构,模型不会因为单点失效而奔溃;缺点是新加入者需要经历相当长的时间才能使自己的密钥得到一定数量用户的代言。

一种更常见的方法是依靠中心化的机构,其中包括对公钥基础设施(PKI)的使用,PKI负责提供创建、吊销、分发以及更新密钥对证书的服务。它需要一些证书颁发机构(CA)才能运行,CA是用于管理与认证一些个体与它们的公钥间的绑定关系的实体。

ITU-T X.509 是公钥证书的格式标准[RFC5280],常见的的包括DER、PEM、PKCS#7、PKCS#12。

可用 openssl 命令来查看网站证书信息:

    openssl x509 -in xxx.pem -text

给出结构大致:

Certificate:  解码后的证书信息
Data: 元数据
Version: 版本,特定的证书类型
Serial Number: 特定证书的序列号
Signature Algorithm: 签名算法
Issuer: 发行者,拥有以下特殊子域:C(国家)、L(地区或城市)、O(组织)、OU(组织单元)、ST(州或省)、CN(通用名称)
Validity: 有效时间
Not Brfore: 起始时间
Not After: 结束时间
Subject: 主题,标识与当前证书相关的实体
Subject Public Key Info: 主题公钥信息,标识公钥的拥有者
Public Key Algorithm: 公钥算法
Public-Key: 公钥
Modulus: 模
...
Exponent: 指数
Signature Algorithm: 签名算法
...
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE----- # ... 根据字段决定值类型,代表密钥/签名等结果内容

在证书撤销的过程中,需要考虑一些问题'如何撤销证书?'、'如何让依赖方知道他们所依赖的证书不再可信?'。

为了验证某个证书,需要建立一条验证(或认证)路径,这条路径应当是一个已被验证过的证书集合,通常会包含依赖方已经的信任锚点(例如,根证书)。验证过程的一个关键步骤在于确定证书链中的一个或多个证书是否已被撤销。若是,则验证路径将失效。

互联网中实现证书撤销的两种方法:证书撤销列表(CRL)和在线证书状态协议(OCSP)[RFC2560]。

CRL:一个被签署的列表,它指定了一套证书发布者认为无效的证书。除了普通CRL外,还定义了一些特殊的CRL类型用于覆盖特殊领域的CRL。

OCSP:一个应用层的请求/应答协议,通常运行在HTTP协议之上。当用户试图访问一个服务器时,在线证书状态协议发送一个对于证书状态信息的请求,服务器回复一个"有效"、"过期"或"未知"的响应。

OCSP克服了CRL的缺陷:必须经常在客户端下载以确保列表的更新。

TCP/IP安全协议与分层

存在与OSI协议栈中各层次以及一些'中间'层的安全协议,如下:

层号     层名称       实例
7 应用层 DNSEC/DKM/EAP/Diameter/RADIUS/SSH/Kerberos/IPsec(IKE)
4 传输层 TLS/DTLS/PANA
3 网络层 IPsec(ESP)
2 链路层 802.1X(EAPoL)/802.1AE(MACSec)/802.11i/WPA2/EAP

网络访问控制

网络访问控制(NAC)是指对于特定系统或用户而言用于授权或拒绝网络通信的方法。

由IEEE定义的802.1X基于端口的网络访问控制(PNAC)标准广泛用于TCP/IP网络,为企业局域网提供安全,其中包括有线和无线网络。PNAC的目的在于只有当系统或用户基于网络接入点完成认证后,才会为其提供网络访问服务。由于常与IETF标准的可扩展身份验证协议(EAP)配合使用[RFC3748],所以802.1X协议有时也称为局域网上的EAP协议(EAPoL)。2010年的版本[802.1X-2010]还包括了802.1AE(IEEE的局域网加密标准,称为MACSec)与802.1AR(面向安全设备表示的X.509证书),还包括了一个比较复杂的MACSec密钥协商协议MKA。

EAP可与多种链路层技术一同使用,并提供多种方法来实现身份验证、授权及计费(AAA)。然而EAP本身并不执行加密,所以它必须与其他一些加密功能矫情的协议一同才能保证安全。如下图是EAP的一个实例设置:

TCP/IP 笔记 - 安全

上图假设了一个包括有线和无线端点的企业网络,这个受保护的网络包括了AAA服务器、特殊虚拟局域网中的内网服务器以及一个不需要认证的虚拟局域网。认证者负责与未认证端点以及AAA服务器进行交互以确定是否给予每个端点访问受保护网络的权限。上图认证者能够以'直通模式'允运行,以帮助认证者免于执行大量的认证方法。

EAP数据包的格式非常简单,如图所示:

TCP/IP 笔记 - 安全

代码字段包含了6中EAP数据包类型之一:请求(1)、响应(2)、成功(3)、失败(4)、初始化(5)、结束(6)。

标识符字段包含了一个由发送者选择的序号,用于匹配请求与响应。

长度字段给出了EAP消息的字节数(含代码、标识符、长度)。

典型的EAP交互过程:

  1. 从认证者发送一个请求消息给端点;

  2. 端点以一条响应消息作为回应,两条消息使用的格式相同。

请求与响应消息的主要目的在于交换实现成功认证所需要的信息,如下图:

TCP/IP 笔记 - 安全

EAP消息承载着端点与认证者之间的认证材料。

EAP是一个支持自身的多路复用与多路分解的分层体系结构,从概念上讲,它包括四个层次:底层、EAP层、EAP端点/认证者层、EAP方法层。底层负责有序的传输EAP帧;EAP层实现可靠性和消除重复;EAP端点/认证者层负责实现端点与认证者协议的消息,基于对代码字段的多路分解实现;EAP方法层包含了所有用于认证的特殊方法,包含任何用于处理大消息的协议操作。

TCP/IP 笔记 - 安全

网络接入认证信息承载协议(PANA)作为EAP的下次,扮演着EAP信息承载者的角色,它使用UDP/IP协议(端口号716),因此能够用于多种类型的链路,并且不限于点对点的网络模型。

PANA的框架包含了三个主要的功能性实体,PANA客户端(PaC)、PANA认证代理(PAA)、PANA中继原件(PRE):

  PANA的用途通常包含认证服务器(AS)和执行点(EP),AS是一个通过访问协议访问的常规AAA服务器。

  PAA负责将认证材料从PaC传输至AS,并且在网络访问被批准或撤销时对EP进行配置。

  PaC与PAA之间的直接通信不能实现时,PRE可用于两者之间的中继通信。

PANA协议由一组请求/响应消息构成,包括一个有"属性-值"对组成的扩展集合。PANA会话包含4个节点:认证/授权、访问、重新认证、终止。重新认证实际上是访问阶段的一部分,所以重新认证后会话的生存期也得到相应的扩展。终止节点一般会以明确的方式进入,也会因为会话超时而进入。

PANA是一个弱传输协议,它按照"stop-and-wait"模式工作,没有使用自适应的重传计时器,不能够对数据包进行重新分组。当出现多个数据包丢失的情况时,它的重传计时器会以指数的方式进行回退。

IP安全(IPsec)

IPsec的操作可分为建立阶段和数据交换阶段。建立阶段负载交换密钥材料并建立安全管理(SA);数据交换阶段会使用不同类型的封装架构,称为认证头部(AH)与封装安全负载(ESP)。

一个完整的IPsec包含了SA建立协议、AH(可选)、ESP以及一些合适的加密套件、配置信息与设置工具。[RFC6071]总结了所有IPsec组件的发展过程与当前规范。

IPsec会有选择地针对某些数据包进行操作,这些操作基于管理员所设定的策略。所有的策略都包含在一个安全策略数据库(SPD)中,逻辑上与每一个IPsec的实现相伴。IPsec还需要两个额外的数据库,称为安全关联数据库(SAD)和端点认证数据包(PAD)。下图简单的描述了需要如何使用这些数据库及如何处理数据包:

TCP/IP 笔记 - 安全

SA

IPsec的第一步就是建立SA,SA是在两个通信方之间建立的单工(单向)认证关联。常见的情况是双方之间的双向通信,因此需要一对SA才能有效地使用IPsec,特殊协议Internet密钥交换(IKE)自动完成这项工作。IKE开始于一个简单的请求/响应消息对,该消息对包括一个建立以下参数的请求:加密请求、完整性保护算法、Diffie-Hellman组,以及根据任何输入的比特串随机生成输出的PRF(PRF用于生成会话密钥)。

IKE的前两次交换称为IKE_SA_INIT和IKE_AUTH,建立一个IKE_SA和CHILD_SA。随后出现两个交换,其中CREATE_CHILD_SA交换用于建立其他的CHILD_SA,INFORMATIONAL交换则用于初始化SA中的变化或收集SA的状态信息。IKE消息封装在UDP中通过端口500或4500发送,而IKE的接收者则应该准备接收来自任何端口的流量。

IKE消息格式如下:

TCP/IP 笔记 - 安全

SPI,安全参数索引,一个64位的号码,用于标识一个特定的IKE_SA,发起者和响应者都会有一个属于自己的SA,所以它们能提供正在使用的SPI,这一对SPI值能够与通信两端的IP地址结合起来用于形成一个有效的连接标识符。

下一个负载字段指出了后面负载的类型。

主要版本字和次要版本字段应分别设置为2和0,当无法维持版本直接的互操作性时,主要版本号就会被修改。

交换类型字段给出了消息的交换类型,包含:IKE_SA_INIT(34),IKE_AUTH(35),CREATE_CHILD_SA(36),INFORMATIONAL(37),IKE_SESSION_RESUME(38),其他数值被保留,240~255范围被留作私人用途。

标志位字段定义了一个3比特位的字段:I(发起者,第3位),V(版本,第4位),R(响应者,第5位)。I由原始发起者设置,接收者会在返回消息中将其清除;V指出一个版本号,高于发送者当前使用的协议的主要版本号;R指出当前消息是之前某一消息的响应,与其使用相同的消息标识符。

消息标识符字段是于TCP序列号类似的功能,标识包含该标识符的数据流的第一个字节。不同的是发起者消息标识符从0开始,而响应者从1开始。无论是在发送还是接收时,消息标识符都会被记录下,这样做可以帮助每一个通信端检测重放攻击。

长度字段统计了IKE消息头部和所有负载的合计大小。

IKEv2负载类型表,数值0表示没有下一个负载:

TCP/IP 笔记 - 安全

"通用"的IKEv2负载头部如下图所示:

TCP/IP 笔记 - 安全

通用的负载头部固定为32位,下一个负载与负载长度字段提供了一个大小可变的负载"链"(最多位65535字节,包括负载头部的4字节)。C位指出当前负载对于一个成功的IKE交换而言被认为是"关键"的。

IKE_SA_INIT与IKE_AUTH交换过程:

TCP/IP 笔记 - 安全

HDR IKE 头部(非有效载荷);SAi1/SAr1(SAi2/SAr2)分别表示发起者和响应者可支持的密码算法套件,数值表示阶段;KEi/KEr表示双方的 Diffie–Hellman密钥交换内容和一次性随机数。

CREATE_CHILD_SA交换用于创建或更新一个CHILD_SA,或用于更新一个IKE_SA。交换过程如下:

TCP/IP 笔记 - 安全

INFORMATIONAL交换用于传输状态与错误信息,通常使用N(通知)负载。交换过程如下:

TCP/IP 笔记 - 安全

AH

IP认证头部(AH)[RFC4302]是IPsec协议套件的可选部分,提供了一种源认证与保护IP数据报完整性的方法。

看下IPsec AH处理后的IP头部(IPsec头部):

TCP/IP 笔记 - 安全

IPsec AH处理后的隧道模式IP头部:

TCP/IP 笔记 - 安全

AH结构:

TCP/IP 笔记 - 安全

下一个头部字段指出下一个类型值。

负载长度字段指出AH的长度。

保留字段作为保留。

安全参数索引字段包含一个32位的位于接收者端的SA标识符,指出AH属于哪个SA,随着每一个SA数据包的发送而增1。

序列号字段,如果开启,则用于重放保护。

完整性校验值字段是可变的,且依赖于使用的密码套件,该字段在长度上保持为32比特的整数倍。

ESP

IPsec的封装安全负载(ESP)[RFC4303],也称作ESP(v3)(注意,其本身并不提供正式的版本号),提供了一个可选的组合,包括机密性、完整性、原始认证以及对IP数据报的反重放保护。

看下IPsec ESP处理后的IP头部(IPsec头部):

TCP/IP 笔记 - 安全

IPsec ESP处理后的隧道模式IP头部:

TCP/IP 笔记 - 安全

ESP结构:

TCP/IP 笔记 - 安全

安全参数索引字段包含一个32位的位于接收者端的SA标识符,指出ESP属于哪个SA,随着每一个SA数据包的发送而增1。

序列号字段,如果开启,则用于重放保护。

负载数据以32位(IPv6中64位)为边界终止,并且最后两个8位字段能够识别填充长度与下一个头部字段值,填充、填充长度、下一个头部字段共同构成了ESP尾部。

完整性校验值字段是一个长度可变的尾部,用于启用完整性支持以及满足完整性检验算法的需要。它会对ESP头部、负载以及ESP尾部进行计算。ICV的长度取决于所选择的特定完整性检验方法,因此它会在相关的SA建立之后才建立起来,并且要求SA在其生存期中不发生改变。

传输层安全(TLS和DTLS)

传输层安全(TLS)用于保证Web通信以及其他流行协议的安全,其面向数据报的版本成为数据报传输层安全(DTLS)。

TLS协议本身分为两层:记录层和上层。如图所示:

TCP/IP 笔记 - 安全

TLS是一个客户端/服务器协议,设计用于为两个应用程序的连接提供安全。记录协议提供分片、压缩、完整性保护及客户端与服务器之间所交换数据的加密服务。信息交换协议(即上层协议)负责建立身份、进行认证、提示警报、以及为用于每一条连接的记录协议提供唯一的密钥材料,其包含4个特殊的协议:握手协议、警告协议、密码变更协议、应用数据协议。

记录协议

记录协议使用一个可扩展的记录"内容类型"值集合来识别可多路复用的消息类型。

在任何给定的时间点时,记录协议有一个活跃的当前连接状态和一组被称为挂起连接状态的状态参数;每一个连接状态又进一步被划分为读状态和写状态;每个状态又指定一个压缩算法、加密算法和用于通信的MAC算法,同时还包括必需的密钥与参数。

TLS记录过程:

TCP/IP 笔记 - 安全

压缩算法可以为NULL压缩协议,即不提供任何压缩,且压缩算法应该是无损的,产出的输出结果不能大于输入记录的1KB。为了防止负载被披露或修改,加密与完整性保护算法会将TLS压缩结构转换为能够在底层传输层连接上发送的TLS密文结构。

消息交换协议 

TLS的三个子协议是通过数字分辨的,这些数字被记录层用于多路复用和多路分解,比如握手协议(22)、警告协议(21)、密码变更协议(20)。

密码变更协议包括一个单字节的消息,该字节的数值为1,该消息的目的在于指出通信一方希望将当前状态修改为挂起状态。如果收到这条消息,就将读挂起状态作为当前状态并指示记录层尽快转换至挂起写状态。

警告协议用于从TLS脸颊的一端向另一端传递状态信息,它可以包括一些终止条件或非致命的错误条件。

握手协议建立了与连接相关的运行参数。它允许TLS端点完成6个主要目标:协商加密算法并交换形成对称密钥时使用的随机值;建立算法运行参数;交换证书并执行互相认证;生成特定的会话密钥;为记录层提供安全参数;验证所有的操作都已正确执行。

握手协议过程:

  1. 客户端向服务端发送第一条ClientHello消息,该消息包含:会话标识符、建议的加密套件变化(CS)、一套可接受的压缩算法、TLS版本号、一个称为ClientHello.random的随机数。

  2. 服务端接收到ClientHello消息,检查其中的会话标识是否存在其缓存中。如果存在,则服务端通过一个简化的握手过程继续之前已有的连接(称为重新开始)。服务端通过ServerHello消息将服务端的随机数ServerHello.random传递至客户端,完成了交换的第一部分。这条消息也包含一个会话标识符,如果它的数值与客户端的数值相同,则表明服务端愿意重新开始;否则其数值为0表示需要开启一个完整的握手过程。如果服务端需要通过身份验证,会要求它在证书(Certificate)消息中提供自己的证书链。如果证书的签名是无效的,那么服务器可能还需要发送一个服务器密钥交换消息,使其在没有证书的情况下通过一个暂时或短暂的密钥生成会话密钥。

  3. 客户端收到服务端返回信息并确认后,以一个握手协议已完成消息(Finished)结束。

如下图:

TCP/IP 笔记 - 安全

在缺乏可靠传输层的情况下提供类似TLS服务的主要挑战在于数据报可能会丢失、重新排序或重复。这些问题会影响到加密与握手协议,这两者都依赖于TLS协议。为了处理这些问题,DTLS为记录层承载的每一条记录添加了一个明确的序列号,在每一条ChangeCipherSpec消息发送之后这些序列号被重置为0。

在DTLS中的MAC计算修改了对应的TLS版本,包含了一个由两个新字段组成的64位块,以允许单独处理每一条记录。注意:在TLS中一个错误的MAC会导致连接终止;而在DTLS中,终止一个完整的连接是没有必要的,接收者会选择简单地丢弃包含错误MAC的记录,或是发送一条警告消息。

重复的消息会被简单地丢弃,或者被视为一个潜在的重放攻击。如果支持重放检测,那么将会在接收端设置一个当前序列号窗口。要求该窗口只是容纳32条消息,建议至少64条。以下列出接收到消息后的行为:

  1. 如果到达记录的序列号小于窗口左边沿对应的数值,那么会将它视为旧的或重复的记录而默默地丢弃;

  2. 那些在窗口之内的记录也会被检查,看是否出现重复;

  3. 如果一条消息在窗口之内并且拥有正确的序列号,即便出现顺序错乱的情况也会将其保留下来;

  4. 而那些拥有错误MAC的消息会被丢弃;

  5. 有正确MAC却超出窗口右边沿的消息会使得右边沿增加。

因此,右边沿代表已验证消息的最高序列号。

为了处理消息丢失的问题,DTLS具有简单的超时和重传功能。重传功能是以消息组的形式运行的,也被称为"班次"。

TCP/IP 笔记 - 安全

上图初始的完整交换(左)包含6个班次的信息,每个班次都能够持续传输。DTLS简化交换(右上)只使用3个班次,且与TLS略不同。DTLS在处理协议时报错一个拥有三个状态的有限状态机(右下)。

状态机的三个状态分别为:准备、发送、等待。状态机由一个重传计时器驱动,它的默认建议值为1秒。如果在超时期限内接收不到某一班次的响应,就会使用相同的握手协议序列号重新传输这一班次。然而需要注意的是,记录层序列号仍然会向前增加。后续重传如何没有获得响应将会使RTX的超时值加倍,至少高达60s。在一次成功传输或一个长的空闲期后会重置该数值。

在DTLS中,当一台服务器接受到一条ClientHello消息,它会生成一条心的包含32位cookie的HelloVerifyRequest消息。后续的ClientHello消息必须包含之前的cookie,否则服务器会拒绝交换。这被DTLS用于防御DoS攻击。

DNS安全(DNSEC)

DNS的安全不仅指DNS中的数据(资源记录,RR)安全,还包含在同步或更新DNS服务器内容时的传输安全。针对其部署的安全机制称为域名系统安全扩展(DNSSEC)[RFC4033][RFC4034][RFC4035]。DNSSEC提供了DNS数据的源认证与完整性保护,以及(有限的)密钥分发设施。DNSSEC还能够进行不存在性验证,DNS响应能够指出某一受保护的特定域名是不存在的并对此提供保护。DNSSEC不能为DNS信息提供保密性、DoS攻击保护以及访问控制。

当执行一个带有DNSSEC的DNS查询时,一个已知安全的解析器就会使用DNS扩展机制(EDNS0),并且将请求中一个OPT元资源记录的DO位置位(表示DNSSEC OK)。该位指出客户端不仅有兴趣而且有能力来处理DNSSEC相关的信息并支持EDNS0。DO位在EDNS0元资源记录的"扩展的RCODE与标志"部分,是其中第2个16位字段的第1位。接收到那些DO位未置位(或不存在)请求时,会禁止服务器返回大多数资源记录,除非这些记录是在请求中明确要求的。

当服务器处理来自一个DNSSEC可用解析器的请求时,它会检测DNS请求的CD(Checking Disabled)位,如果该位置位,那么表明客户端愿意接收包含未验证数据的响应。在准备一个响应时,服务器通常会利用密码方法验证要返回的数据,成功的验证结果会使得响应中的AD(Authentic Data)位置位[RFC4035]。如果拥有一条到达服务器的安全路径,那么一个安全已知但未验证的解析器在原则上是能够信任这条信息的。然而,最好的情况是使用验证存根解析器,它能够进行加密验证,从而将查询的CD位置位。这样不仅提供了端到端的DNS安全(即中间解析器不需要是可信的),还减少了中间服务器的计算负担;否则,这些中间服务器不得不进行密码验证。

DNSSEC 资源记录

DNSKEY,用以维护公钥。密钥只能与DNSSEC一起使用;其他的资源记录可能用于维护针对其他用途的密钥或证书。

DNSKEY资源记录格式如下图:

TCP/IP 笔记 - 安全

DNSKEY资源记录的RDATA部分包含一个只用于DNSSEC的公钥,标志字段包含了一个区域密钥指示符(第7位),如果置位,那么DNSKEY资源记录拥有者的名称必须为区域的名称,并且所包含的密钥也被称为区域签名密钥(ZSK)或密钥签名密钥(KSK),如果未置位,那么记录将会维护另一种不能用于验证区域签名的DNS密钥;一个安全入口点指示符(第15位)作为调试或签名软件时的一条提示,能够根据密钥的用途做出明智的猜测,签名验证不会解释SEP位,但该位置位的密钥通常为KSK,并通过验证子区域的密钥来确保DNS层次结构的安全;一个撤销指示符(第8位),如果置位,则表示密钥不能用于验证。算法字段指出了签名算法,根据[RFC4034],只有DSA与具有SHA-1的RSA(值分别为3和5)才被定义用于DNSKEY资源记录。公钥字段维护了一个公钥,它的格式依赖于算法字段。

DS,授权签名者资源记录用于指定一条DNSKEY资源记录,通常从一个父区域到一个子区域。

DS资源记录格式如图:

TCP/IP 笔记 - 安全

密钥标签字段包含了对一条DNSKEY资源记录的非唯一参考。

算法字段使用了DNSKEY资源记录的算法字段相同的数值。

摘要类型字段指出了所用的签名类型[RFC4034]中只定义了数值1(SHA-1),SHA-256是通过[RFC4509]指定的。

摘要字段包含了将要引用的DNSKEY资源记录的摘要,该摘要计算方法如下:

    摘要 = 摘要算法(DNSKEY所有者名|DNSKEY RDATA)

此处的"|"是连接运算符,而DNSKEY RDATA的数值是根据引用的DNSKEY资源记录来计算的,计算方法如下:

    DNSKEY RDATA = 标志 | 协议 | 算法 | 公钥

在SHA-1情况下,摘要长度为20字节;在SHA-256情况下,长度为32字节。

NSEC/NSEC3,NextSECure,下一个安全资源记录用于规范有序的名称或一个NS类型的RRset(资源记录集)授权点中维护"下一个"RRset所有者的域名,它还维护位于NSEC资源记录的所有者名称中的RR类型列表,这样能够为区域结构提供认证与完整性验证。

NSEC资源记录格式如图:

TCP/IP 笔记 - 安全

下一个域名字段维护一个区域的规范有序的域名链中的下一个条目。

类型位图字段维护了一张关于RR类型的位图,这些RR类型记录在NSEC资源记录所有者的域名中。

NSEC3是对NSEC结构做的优化,旨在消除"任何人能够通过遍历NSEC链而列举出一个区域中的权威记录"这个问题(也被称为区域列举)。

NSEC3资源记录格式如图:

TCP/IP 笔记 - 安全

散列算法字段标识了应用于下一个所有者名称的散列函数,以产生下一个散列的所有者字段。

标志字段的低比特位包含了一个opt-out标志,如果置位,它将指出NSEC3记录可能包含未签名的授权。

迭代次数字段指出散列函数使用了多少次,较大的迭代次数有助于防止找到与NSEC3记录中的散列数值相关的所有者名称(字典攻击)。

混淆值长度字段给出了混淆值字段的字节长度,包含了一个在计算散列函数之前附加于原所有者名称的数值,目的在于帮助抵御字典攻击。

为了获得下一个散列所有者字段的散列值,需要进行以下计算:

    IH(0) = H(所有者名称 | 混淆值)
IH(k) = H(IH(k - 1) | 混淆值), 若 k > 0
下一个散列所有者 = H(IH(迭代次数) | 混淆值)

其中H是散列算法字段指定的散列函数,所有者名称必须按照标准的格式。迭代次数与混淆值取自NSEC3资源记录的相关字段。

为了避免混淆NSEC与NSEC3资源记录类型,[RFC5155]在NSEC3资源记录的区域中分配并要求使用特殊的安全算法编号6和7,作为标识符3(DSA)和5(SHA-1)的别名。

RRSIG,资源记录签名的资源记录用于签署并验证RRset中的签名。区域中每一条授权的资源记录都必须签名,一条RRSIG资源记录包含了某一特定RRset的数字签名以及使用哪一个公钥来验证签名的信息。

RRSIG资源记录格式如图:

TCP/IP 笔记 - 安全

覆盖类型字段指出了签名适用的RRset类型,它的数值来自标准的RR类型集合。

算法字段指出了签名算法。

标签字段给出了在RRSIG资源记录的原所有者名称中的标签数目。

源TTL字段维护了一份TTL副本,这份副本是当RRset出现于授权区域时保留下来的。

签名到期与签名成立字段指出了一个签名有效期的开始和结束时间。

密钥标签字段标识那些用于获得某种特殊公钥的DNSKEY资源记录。

DNSSEC运行 

对于一个特殊的资源记录而言,需要有一个定义良好的规范形式:

  1. 每一个域名都是一个完全限定域名并被完全展开(无压缩标签)。

  2. 在所有者名称中的所有大写的US-ASCII码字符都需要被它们的小写版本代替。

  3. 对于任何类型号为2~9、12、14、15、17、18、21、24、26、33、35、36、39以及38的记录,在它们的RDATA部分出现的域名中,所有大写的US-ASCII码字符都需要被它们的小写版本代替。

  4. 任何通配符都不会被取代。

  5. 当出现在源权威区域或覆盖RRSIG资源记录的源TTL字段,TTL将会设置为原始值。

DNSSEC依赖于签名区域。这样的区域包括RRSIG、DNSKEY以及NSEC(或NSEC3)资源记录,而且如果有一个签名授权点,它还可能包含DS资源记录。签名使用公钥加密,公钥的存储于分发通过DNS来完成。

如下图展示了位于父子区域之间的抽象授权点:

TCP/IP 笔记 - 安全

父区域包含了自己的DNSKEY资源记录,它能够提供与使用RRSIG资源记录来签名一个区域中的所有授权RRset的私钥相关的公钥。父区域中的一条DS资源记录提供子顶点的一条DNSKEY资源记录的散列值,这样就能见了起一条从父区域到子区域的信任链。一个信任父区域的DS资源记录的验证解析器也能验证子区域的DNSKEY资源记录,以及最终的RRSIG和子区域中签名的RRset(该情况只有在验证者拥有一个与父区域DSNKEY资源记录相连的信任根节点时才会发生)。

事务认证(TSIG,TKEY,SIG(0))

DNSSEC提供了数据的源认证与区域数据的完整性保护,而事务认证为客户端与服务器之间不检查交换内容正确性的特殊事务提供了完整性保护与认证。DNS中的事务(如区域传输、动态更新)安全并不直接保护DNS的内容,所以它和DNSSEC是互补的,需要能够被一同部署。

主要有两种方法来认证DNS的事务:TSIG和SIG(0)。SIG使用共享密钥而SIG(0)使用公钥/私钥对,为了缓解部署的负担,可以使用TKEY资源记录类型来帮助形成TSIG或SIG(0)的密钥。

针对DNS或事务签名的密钥事务认证(TSIG)[RFC2845]5]使用基于共享密钥的签名为DNS交换添加事务认证,TSIG使用一个按需计算并且只用于保障一次事务的TSIG伪资源记录。

TSIG伪资源记录格式如图:

TCP/IP 笔记 - 安全

上面的资源记录是包含在DNS请求与响应的附加数据部分发送的。

算法名称字段指出使用什么算法。

签名时间字段是按照UNIX系统的时间格式组织的,并且给出了消息内容被签署的时间,此字段隐藏在数字签名中,被设计用于检测并抵御重放攻击,此处使用一个绝对时间的结果是,使用TSIG的端点必须在更新字段指定秒数内对时间达成一致。

MAC大小字段给出了MAC字段中包含的MAC与其依赖的特殊MAC算法所需的字节数。

源ID字段是该消息的一个标识,与DNS的事务ID匹配。

错误字段用以承载错误信息。

其他长度字段给出了其他数据字段的字节数,一般用来运送错误的消息。

SIG(0)[RFC2931]没有覆盖DNS中静态的记录,而是为交换动态地生成,SIG(0)的0部分指一条被签署资源记录中数据的长度。SIG(0)记录原则上能够替代TSIG资源记录,并达到相同的结果,但他们是以不同的方法实现的。更重要的是,SIG(0)将信任基础放置于公钥中来代替共享密钥。

TKEY元资源记录类型旨在简化DNS交换安全的部署,为了完成这项工作,它会动态创建TKEY资源记录并添加到DNS请求与响应的附加信息部分发送出去,它们能够包含密钥或者用于形成密钥的资料,比如DH公共数值。

域名密钥识别邮件 

域名密钥识别邮件(DKIM)[RFC5585]提供了一个实体与一个域名之间的关联,从而决定哪一方发送初始消息,特别是以电子邮件形式。域名密钥识别邮件的工作是通过在基本的Internet消息格式中添加一个DKIM签名实现的[RFC5322],该字段包含了对消息头部和消息体的数字签名。DKIM取代了早期称为域名密钥的标准,该标准使用域名密钥签名字段。

为生成一条消息的数字签名,签名域表示符(SDID)会使用RSA/SHA-1或者RSA/SHA-256算法及相关的私钥。SDID来自DNS的域名,并用于检索以TXT资源记录存储的公钥。一个DKIM签名会通过Base64被编码为一个消息头部字段,该签名能够签署一个明确列出的消息字段与消息体集合。

当接收到一封电子邮件时,邮件传输代理会使用SDID来实现一个DNS查询,从而找出相关的公钥。该公钥会在之后用于验证签名,这样就避免了请求一个PKI的工作。所拥有的域名是由域本身和选择器(公钥选择器)一起构成的。例如,在域example.com中的选择器key35的公钥是一条由key35._domainkey.example.com拥有的TXT资源记录。

参考:

《TCP IP 详解卷1:协议》

RFC官方文档