一 复习与目标
1 复习
- 简单密码学、对称加密与非对称加密
- 数字签名、数字证书
- SSL/TLS
- HTTPS = HTTP + SSL/TLS,SSL/TLS为HTTP提供了保密性、完整性和鉴别性
2 目标
注:调优提早说明是担忧讲完H二、WebSocket协议,致使前面的协议忘的差很少了,因此提早学习,提早使用上(偏重实战)。html
二 TCP性能调优
1 性能检查清单
- 服务器内核升级到最新版本(Linux:3.7 +)
- 确保启动窗口缩放;
- 确保cwnd大小为 10:
- 禁用空闲后的慢启动;
- 减小传输冗余数据;
- 压缩要传输的数据;
- 把服务器放到离用户近的地方以减小往返时间(CDN);
- 尽最大可能重用已经创建的 TCP 链接:启动TFO。
2 上述优化详解
(1)服务器内核升级
(2)启动窗口缩放:RFC 1323
- TCP的Window Size(rwnd,Receiver Window)起初只有65535字节。
- 1992年RFC 1323添加Window Scale选项,将其提高到了1G字节。
- Window Size过小时,在带宽延迟积很高的网络中,TCP没法获取最优性能。
# 检查是否开启,通常默认开启
$> sysctl net.ipv4.tcp_window_scaling
# 开启指令
$> sysctl -w net.ipv4.tcp_window_scaling=1
(3)增大初始拥塞窗口:RFC 6928
- initcwnd起初默认为1,1999年RFC 2581将其增长到4,2013年RFC 6928提升到10。
- 当cwnd=10,一次RTT就能发送10个MSS大小的TCP报文。即相比cwnd=1,发送速度翻了10倍。
注:cwnd用于控制发送速度(一次RTT能发送多少个报文段),MSS用于控制单个报文段的大小。nginx
(4)慢启动重启(Slow-Start Restart)
- 链接空闲必定时间后重置链接的拥塞窗口,即设置cwnd为初始值。
# 查看
$> sysctl net.ipv4.tcp_slow_start_after_idle
# 禁用
$> sysctl -w net.ipv4.tcp_slow_start_after_idle=0
(5)TCP快速打开(Tcp Fast Open): RFC 7413
- 在某些条件下,容许在第一个SYN 分组中发送应用程序数据。TFO是一种新的优化选项,须要客户端和服务器共同支持。
# 查看
$> sysctl net.ipv4.tcp_fastopen
# 修改
$> sysctl -w net.ipv4.tcp_fastopen=3
# nginx 编译时添加
--with-cc-opt=-DTCP_FASTOPEN=23
# nginx.conf配置
listen 443 ssl http2 fastopen=3 reuseport default_server;
注:yum或者apt-get可使用从新编译替换来升级nginxweb
- 下载nginx源码
- 编译 ./configure 添加须要的模块或者配置
- make
- 复制objs目录下的nginx替换/usr/sbin/nginx
3 知识点补充
(1)Linux下查看socket统计信息:ss
# 显示全部链接
$ ss | less
# TCP链接过滤出来
$ ss -at
# 打印进程名和进程号
$ ss -ltp
# 打印统计概要
$ ss -s
# 显示目的端口是443或80的套接字
$ ss -nt '( dst :443 or dst :80 )'
# 具体请自行查询资料
(2)带宽延迟积
- BDP(Bandwidth-delay product,带宽延迟积):数据链路的容量与其端到端延迟的乘积。这个结果就是任意时刻处于在途未确认状态的最大数据量。
- 带宽延迟积取决于拥塞窗口(cwnd)和接收窗口(rwnd)的最小值,带宽延迟积(1次RTT内) = Math.min(rwnd * window scale,cwnd * MSS)
- 实验1:带宽不重要!
- 假设MSS = 1460,cwnd = 10,那么一次RTT内的最大数据量为1460 * 10 约16KB,RTT为100ms
- 带宽 = 16 KB / 0.1 s= 1 310 720 bit/s = 1.31 Mbit/s
- 即当前状态即便增长带宽,也没法使得TCP数据交换速度提高。
- 实验2:请开启窗口缩放!
- 不开启窗口缩放时,rwnd最大值为64KB
- 假设如今RTT为100ms,网络可用带宽为10Mbit/s,理论带宽延迟积为100ms * 10Mbit/s = 122.1KB
- 可是实际带宽延迟积最大值为64KB,远远小于122.1KB,因此须要开启窗口缩放来提高rwnd的大小。
(3)队首阻塞(HOL,Head of Line)
- TCP 分组都会带着一个惟一的序列号被发出,而全部分组必须按顺序传送到接收端。
- 若是中途有一个分组没能到达接收端,那么后续分组必须保存在接收端的TCP 缓冲区,等待丢失的分组重发并到达接收端。
- 这一切都发生在TCP 层,应用程序对TCP 重发和缓冲区中排队的分组一无所知,必须等待分组所有到达才能访问数据。
- 在此以前,应用程序只能在经过套接字读数据时感受到延迟交付。这种效应称为TCP 的队首阻塞。
三 SSL/TLS性能调优
1 性能检查清单
- 要最大限制提高 TCP 性能,参考第二章;
- 把 TLS 库升级到最新版本,在此基础上构建(或从新构建)服务器;
- 复用Session:会话缓存和无状态恢复;
- 在接近用户的地方完成 TLS 会话,尽可能减小往返延迟(CDN);
- 配置 TLS 记录大小,使其刚好能封装在一个TCP段内:超出一个段将分段发送,效率变低,使用对的算法使TLS记录又短又安全;
- 确保证书链不会超过拥塞窗口的大小,从信任链中去掉没必要要的证书,减小链条层次;
- 禁用服务器的 TLS 压缩功能;
- 启用服务器对 SNI 的支持;
- 启用服务器的 OCSP 封套功能;
- 追加 HTTP 严格传输安全首部。
2 上述优化详解
(1)升级TLS库
# 升级openssl 1.1.0
# 查看版本
openssl version -a
# 下载编译安装 https://blog.csdn.net/kadwf123/article/details/80809004
# nginx升级到1.13并配置开启便可
(2)复用Session
- 概述:复用Session可以实现简化握手
- 减小了CPU消耗,由于不须要进行非对称密钥交换的计算。
- 提高访问速度,不须要进行彻底握手阶段二,节省了一个 RTT 和计算耗时。
Session Cache(会话缓存)算法
- 概述:使用 client hello 中的 session Identifier查询服务端的 session cache, 若是服务端有对应的缓存,则直接使用已有的 session 信息(加密套件和密钥)提早完成握手,称为简化握手。
- 缺点:
- 消耗服务端内存来存储 session 内容
- nginx,apache 只支持单机多进程间共享缓存,不支持多机间分布式缓存
- 优势:
- session id 是 TLS 协议的标准字段,市面上的浏览器所有都支持 session cache
- 开启:
# nginx开启
# builtin a cache built in OpenSSL; used by one worker process only
# shared a cache shared between all worker processes
ssl_session_cache builtin:1000 shared:SSL:10m;
Session Ticket(无状态恢复)chrome
- 概述:server 将 session 信息加密成 ticket 发送给浏览器,浏览器后续握手请求时会发送 ticket,server 端若是能成功解密和处理 ticket,就能完成简化握手。相似java servlet中session与token。
- 缺点:
- session ticket 只是 TLS 协议的一个扩展特性,目前的支持率不是很普遍,只有 60% 左右。
- session ticket 须要维护一个全局的 key 来加解密,须要考虑 KEY 的安全性和部署效率。
- 开启:
# 开启session ticket
# 具体设置请参考nginx官网
ssl_session_tickets on;
ssl_session_timeout 60m;
Handshake Protocol: New Session Ticket
Handshake Type: New Session Ticket (4)
Length: 198
TLS Session Ticket
Session Ticket Lifetime Hint: 3600
Session Ticket Length: 192
Session Ticket: e3ed09ee89745302e35a2d829ac825504460b4d7e7f94c9a...
分布式状况shell
- Seesion绑定:把相同的客户端 IP 或相同的 TLS 会话 ID 路由到同一台服务器能够最好地利用会话缓存;
- 缓存共享:在不适宜使用“单一”负载均衡策略的状况下,应该为多台服务器配置共享缓存,以便最好地利用会话缓存;
(3)证书链优化
(4)禁用TLS 压缩
- TLS 内置的小功能,就是支持对记录协议传输的数据进行无损压缩。
- 缺点:
- “CRIME”攻击会利用 TLS 压缩恢复加密认证 cookie,让攻击者实施会话劫持
- 传输级的 TLS 压缩不关心内容,可能会再次压缩已经压缩过的数据(图像),双重压缩会浪费服务器和客户端的CPU 时间
- 大多数浏览器会禁用TLS 压缩
注:抱歉这个也没找到如何禁用...
(5)服务器名称指示(SNI)
- 如何但愿一个公有IP地址(同一端口:443)中使用多个虚拟主机(多个域名)就须要使用SNI。
- TLS 协议的拓展,容许客户端在握手之初就指明要链接的主机名。Web 服务器能够检查SNI 主机名,选择适当的证书,继续完成握手。
注:具体参考:https://blog.csdn.net/xifeijian/article/details/56012586
(6)应用层协议协商(NPN和ALPN)
# Server Hello截取报文
Extension: next_protocol_negotiation (len=12)
Type: next_protocol_negotiation (13172)
Length: 12
Next Protocol Negotiation
Protocol string length: 2
Next Protocol: h2
Protocol string length: 8
Next Protocol: http/1.1
# Client Hello截取报文
Extension: application_layer_protocol_negotiation (len=14)
Type: application_layer_protocol_negotiation (16)
Length: 14
ALPN Extension Length: 12
ALPN Protocol
ALPN string length: 2
ALPN Next Protocol: h2
ALPN string length: 8
ALPN Next Protocol: http/1.1
# Server Hello截取报文
Extension: application_layer_protocol_negotiation (len=5)
Type: application_layer_protocol_negotiation (16)
Length: 5
ALPN Extension Length: 3
ALPN Protocol
ALPN string length: 2
ALPN Next Protocol: h2
(7)OCSP stapling
- CRL(Certificate Revocation List,证书撤销名单)是RFC 5280 规定的一种检查全部证书状态的简单机制:每一个证书颁发机构维护并按期发布已撤销证书的序列号名单。
- OCSP(Online Certificate Status Protocol,在线证书状态协议),提供了一种实时检查证书状态的机制。
- 与CRL包含被撤销证书的序列号不一样,OCSP 支持验证端直接查询证书数据库中的序列号,从而验证证书链是否有效。总之,OCSP 占用带宽更少,支持实时验证。
- OCSP要求CA站点必须处理实时查询,CA站点可能网络不稳定,RTT比较大。因而OCSP stapling实现不直接向 CA 站点请求 OCSP 内容。
- 原理:浏览器发起 client hello 时会携带一个 certificate status request 的扩展,服务端看到这个扩展后将 OCSP内容直接返回给浏览器,完成证书状态检查。
# Nginx开启OCSP stapling
ssl_stapling on;
# 具体参考:https://imququ.com/post/why-can-not-turn-on-ocsp-stapling.html
# 抓包
Certificate Status
Certificate Status Length: 471
OCSP Response
responseStatus: successful (0)
responseBytes
ResponseType Id: 1.3.6.1.5.5.7.48.1.1 (id-pkix-ocsp-basic)
BasicOCSPResponse
signature: 560a859a0126b0dc08e3f9a7431056bdf10de99e4e6a6d34...
......
(8)HTTP严格传输安全(HSTS)
- HTTP 严格传输安全(HSTS,Strict Transport Security)是一种安全策略机制,它能让服务器经过简单的HTTP 首部(如Strict-Transport-Security: max-age=31536000)上述对适用的浏览器声明访问规则。
- 全部对原始服务器的请求都经过 HTTPS 发送;
- 全部不安全的连接和客户端请求在发送以前都应该在客户端自动转换为 HTTPS;
- 万一证书有•错误,则显示错误消息,用户不能回避警告;
- max-age 以秒为单位指定 HSTS 规则集的生存时间(例如,max-age=31536000 等于缓存365 天);
- 用户代理能够根据指令在指定的证书链中记住某主机的指纹,以便未来访问时使用,从而有效限制证书颁发机构在特定时间(由max-age 指定)内可颁发证书的范围。(可选的)。
# Nginx 配置
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
(9)加密套件选择
非对称密钥交换算法。建议优先使用 ECDHE,禁用 DHE,次优先选择 RSA。
证书签名算法。因为部分浏览器及操做系统不支持 ECDSA 签名,目前默认都是使用 RSA 签名,其中 SHA1 签名已经再也不安全,chrome 及微软 2016 年开始再也不支持 SHA1 签名的证书 。
对称加解密算法。优先使用 AES-GCM 算法,针对 1.0 以上协议禁用 RC4( rfc7465)。
内容一致性校验算法。Md5 和 sha1 都已经不安全,建议使用 sha2 以上的安全哈希函数。
参考: