Blog

home category

HTTP/2服务器 - 工具

26 Aug 2016

查看TLS内容,数字证书在TLS协商对称密钥时由服务器发送给浏览器,其中包含一把公钥,用于加密pre-master key。浏览器需要证明这把公钥确实属于服务器(协商过程明文进行,需防止中间人攻击),数字证书就是证明方式。数字证书由CA颁发,是CA利用私钥将域名、服务器等相关信息加密后得到的。浏览器的证书管理器预先安装受信任CA的公钥,拿到数字证书后利用受信任CA的公钥解密得到携带的受认证的信息。

Let’s Encrypt: How It Works

Let’s Encrypt和ACME(Automated Certificate Management Environment)协议(通过JSON-over-HTTPS接口,来自动化对域名认证证书的管理)的目标是能完全自动的搭建起HTTPS服务并获取浏览器信任的证书。需要在server上运行一个证书管理代理(certificate management agent)。

完成整个过程需两步,首先agent向CA证明自己管理着域名,之后agent可以为这个域名申请、更新、注销认证证书。

第一步,agent第一次和Let’s Encrypt CA通信时会生成一对密钥,并将需要认证的域名发送给Let’s Encrypt CA。为了证明域名确实受agent管理,Let’s Encrypt CA会给出一个或几个证明方式,例如

  • 要求agent提供域名的DNS
  • 要求agent利用此域名定位一个资源

agent需要完成证明方式中的一种,例如按要求将资源ed98使用https://example.com/8303定位来证明agent管理着example.com。agent还需要将公钥交给Let’s Encrypt CA。为了证明收到的公钥确实属于agent,Let’s Encrypt会生成一个随机量,要求agent使用私钥加密并返回。若Let’s Encrypt CA可以访问到资源,且利用公钥解密得到随机量,通过证明,称密钥对为’authorized key pair’ for example.com,用于后续安全通信。

How it works: Challenge
引用:https://letsencrypt.org/how-it-works/

完成证明后,对域名的证书操作将非常简单,agent只需将管理信息使用私钥加密后发送给Let’s Encrypt CA即可。

How it works: Authorization
引用:https://letsencrypt.org/how-it-works/

申请证书,发送PKCS#10 CSR(Certificate Signing Request),其中包括需要签名的公钥和域名相关信息,使用CSR中公钥对应的私钥签名,这些信息再通过authorized key pair的私钥加密。Let’s Encrypt CA收到后对两个签名进行认证,然后将公钥、域名等相关信息利用CA的私钥加密得到的证书返回给agent。

撤销证书过程类似,agent利用authorized key pair的私钥加密需撤销的证书后发送给Let’s Encrypt CA。证书撤销后CA将撤销信息发送到normal revocation channels(如CRLs, OCSP),用于浏览器等更新。

Certbot client,之前称为Let’s Encrypt Client,是推荐使用的agent工具,能够从Let’s Encrypt获取、更新、撤销证书。

HSTS & DNSSEC

HTTP严格传输安全(HTTP Strict Transport Security, HSTS)是IETF发布的互联网安全策略机制(RFC 6797)。HTTPS能实现安全的连接,但因为用户在输入URI时常忽略https协议部分,通过http 301响应跳转到https。中间人可以利用这个疏漏,实施SSL剥离攻击(SSL stripping attacks, 或称为protocol downgrade attacks),拦截不安全的http连接,将后续连接修改为http来阻止安全连接。

HSTS强制浏览器使用https,并且当证书无法验证时,如已过期等,用户无法忽略浏览器给出的警告继续访问。实现方式包括

  • 响应头部Strict-Transport-Security: max-age=31536000; includeSubDomains要求浏览器在未来1年中总是使用https发起连接,子域名继承相同策略。非HTTPS连接忽略此头部。
  • 因为通过响应头部不能安全处理第一次访问,可以让浏览器预置HSTS列表,但不能覆盖所有网站
  • 可以将HSTS加入DNS纪录中,通过DNSSEC保证DNS纪录的可靠性,目前没有广泛部署

域名系统安全扩展(Domain Name System Security Extensions, DNSSEC)由IETF发布,用于对DNS客户端接收到的DNS纪录的来源进行认证,并验证不存在性和校验数据完整性。

OCSP

OCSP(Online Certificate Status Protocol, RFC 6960)是一种互联网协议,用于查询X.509数字证书是否有效,作为CRL(certificate revocation lists)的替代协议。

OCSP服务器通常由证书签发CA提供,客户端和OCSP服务器通常使用HTTP通信。当浏览器和服务器进行TLS握手时,会尝试从OCSP服务器获取证书状态,了解证书是否已被注销,在确认前无法判断证书是否有效,因此会阻塞TLS握手。并且因为和OCSP服务器之间需完成一个完整的HTTP请求-响应过程,可能消耗较长时间。

OCSP Stapling(OCSP装订,TLS Certificate Status Request extension)是OCSP的替代方案。服务器预先缓存OCSP响应,当客户端和服务器进行TLS握手时发送缓存,避免客户端再向OCSP服务器发送请求。OCSP Stapling解决了OCSP多数不足,包括缓解了OCSP服务器的压力,避免客户端向第三方询问造成可能的不安全,也避免OCSP未响应情况下的不确定性。唯一增加的风险是OCSP Stapling缓存的响应在更新前过期。

客户端接收到的OCSP Stapling响应(OCSP服务器响应)包含两部分:response data和certificate,即证书是否撤销的验证信息和签发此证书的各级CA的证书。因为验证信息是由OCSP服务器签名的,不用担心OCSP Stapling响应被篡改。

验证

验证OCSP Stapling状态和查看OCSP响应

openssl s_client -connect zp25.ninja:443 -status -tlsextdebug < /dev/null 2>&1 \
  | grep -i "OCSP response"

查看OCSP响应,或通过grep仅查看OCSP Stapling状态。

客户端在TLS握手时需在ClientHello信息中明确传入Certificate Status Request extension告诉服务器希望收到OCSP响应,通过-status选项指定。服务器通过Certificate Status Request extension response返回OCSP响应。-tlsextdebug选项可打印出服务器接收到的所有TLS extensions。测试时返回错误

verify error:num=20:unable to get local issuer certificate
verify return:0

尝试传入根证书,从钥匙串访问中导出对应根证书,使用-CAfile root.pem传入,验证通过。

其他选项如-showcerts查看整个证书链,默认仅返回服务器的CA证书。可取出链中各证书,Let’s Encrypt CA签发的服务器证书链为3级,其中0是服务器证书,1是中间证书(Let’s Encrypt Authority x3),根证书(DST ROOT CA x3)无需添加入chain因此省略,可使用之前导出的根证书。

# 可查看各证书的Common Name
openssl x509 -noout -subject -in root.pem

# 可查看各证书的OCSP服务器地址
> openssl x509 -noout -ocsp_uri -in site.pem
http://ocsp.int-x3.letsencrypt.org/

# 尝试从OCSP服务器获取OCSP响应
openssl ocsp -CAfile root.pem -issuer intermediate.pem -cert site.pem -no_nonce -text \
  -url http://ocsp.int-x3.letsencrypt.org/ -header "HOST" "ocsp.int-x3.letsencrypt.org"

获取信息和OCSP响应。

ALPN

Application-Layer Protocol Negotiation是一个TLS扩展,用于在TLS握手阶段进行应用层协议协商。服务器和客户端应该具有利用任意应用层协议通信的能力,但因为预先为每个协议预定端口并配置所有服务器和客户端支持此协议的开销大,通常重用常用通信端口并通过额外机制协商使用的应用层协议。例如使用HTTP预留的80端口,并使用Upgrade头部机制协商。

若使用HTTPS预留的443端口,也可以使用HTTP的Upgrade头部,但因为TLS握手本身就多了一个RTT,Upgrade协商还要多一个RTT效率不高,因此考虑将协商过程在TLS握手阶段完成,使用ALPN实现。在TLS握手阶段

  • ClientHello多加一个ProtocolNameList字段,包含支持的应用层协议
  • 服务器检查ProtocolNameList并在ServerHello中添加ProtocolName字段返回选择的协议

主流浏览器已支持HTTP/2,但其他互联网设备升级支持HTTP/2还需要很长一段时间,因此在使用HTTP/2之前需要确认服务器和中间设备是否支持HTTP/2,HTTPS连接使用ALPN。

NPN(Next Protocol Negotiation)是Google在SPDY中开发的一个扩展,IETF在NPN的基础上发布了ALPN。NPN已被废弃,应配置升级到ALPN,OpenSSL从1.0.2开始支持ALPN,Ubuntu 16.04可用。

SNI

Server Name Indication是一个TLS扩展,若一个IP为多个站点服务,这些站又有各自不同的TLS证书,SNI允许客户端在握手前指明要连接的主机名,服务器查询SNI主机名并选择适当的证书进行握手。

主流浏览器已支持TLS/SNI,OpenSSL从0.9.8f开始支持。

Manual