java中的接口是类吗
635
2022-10-09
SSL/TLS深度解析--TLS性能优化(SSL/TLS安全评估报告)
TCP 优化
Linux系统内核参数优化
[root@~]# cat /etc/redhat-release;uname -r CentOS Linux release 7.5.1804 (Core) 3.10.0-862.11.6.el7.x86_64
TLS 的下一层是 TCP 协议,所以对 TCP 的优化是可以直接影响到 TLS 的性能效率。
在对 TCP 的优化中,主要涉及以下几个概念:
(1)拥塞控制(congestion control)机制:在一个 TCP 连接开始时,不知道对方的速度有多快。如果有足够大的带宽,服务器端可以用最快的速度传送数据,但是如果对方的网络很慢,服务器发送的数据太多的话,会压跨连接,导致连接中断。所以,每个 TCP 连接都有一个称为拥塞窗口(cwnd = congestion window)的速度极限。这个窗口最初较小,在通信的过程中,如果双方都能接受这个速度,那么会加大这个拥塞窗口的值(初期增长很快,翻倍增长),这种机制被叫做慢启动(slow start)。
拥塞控制机制对于 TLS 连接的影响比较大,TLS 握手消耗了宝贵的初始连接字节(当拥塞窗口较小时);如果拥塞窗口足够大,那么慢启动不会有额外的延迟。但是,如果握手消息长度超过了拥塞窗口大小,发送方将必须把这个长信息拆分成两块,先发送一块,等待确认(1个往返),增加拥塞窗口,然后再发送剩下的部分。这样就增加了由 TLS 握手造成的延时。
(2) 慢启动阈值 ssthresh(避免 cwnd 增长过快,网络无法承担,造成丢包)
如果 cwnd 小于 ssthresh,表示在慢启动阶段,cwnd是翻倍增长的;如果 cwnd 大于 ssthresh,那么表示在拥塞避免阶段,这时候 cwnd 不再像慢启动阶段那样翻倍增长,而是线性增长,尽量避免网络拥塞。
(3) 接收窗口(rwnd),用来表示最多能保存多少数据,实际中接收窗口rwnd的合理值取决于BDP的大小,也就是带宽和延迟的乘积。如果带宽是 80Mbps,延迟是 100ms,那么计算过程如下:
BDP = 80Mbps 100ms = (80 / 8) (100 / 1000) = 1MB = 1024KB = 1048576B
TCP 用16位来记录窗口大小,也就是说最大值是64KB,如果超过这个值,就需要 tcp_window_scaling 机制(默认是开启)。配置内核参数中接收缓冲的大小,就可以控制接收窗口的大小:
net.ipv4.tcp_rmem =
[root@~]# sysctl -a |grep ssthresh net.ipv4.tcp_max_ssthresh = 0 #在虚拟机中 [root@~]# sysctl -a |grep tcp_window_scaling net.ipv4.tcp_window_scaling = 1 [root@~]# cat /proc/sys/net/ipv4/tcp_rmem # rwnd值 4096 87380 6291456 [root@~]# sysctl -a |grep tcp_moderate_rcvbuf net.ipv4.tcp_moderate_rcvbuf = 1 [root@~]# sysctl -a |grep adv_win_scale net.ipv4.tcp_adv_win_scale = 1 [root@~]# sysctl -a |grep start_after_idle net.ipv4.tcp_slow_start_after_idle = 1 # 设置cwnd [root@~]# ip route default via 172.16.216.2 dev ens33 169.254.0.0/16 dev ens33 scope link metric 1002 172.16.216.0/24 dev ens33 proto kernel scope link src 172.16.216.188 [root@~]# ip route | while read p; do ip route change $p initcwnd 10; done [root@~]# ip route default via 172.16.216.2 dev ens33 initcwnd 10 169.254.0.0/16 dev ens33 scope link metric 1002 initcwnd 10 172.16.216.0/24 dev ens33 proto kernel scope link src 172.16.216.188 initcwnd 10 # initcwnd 10:初始化cwnd # 单方面提升发送端 cwnd 的大小并不一定有效,因为网络中实际传输的未经确认的数据大小取决于 rwnd 和 cwnd 中的最小值,所以一旦接收方的 rwnd 比较小的话,会抑制 cwnd 的发挥。 # 设置initrwnd(linux kernel 2.6.33 and newer) [root@~]# ip route default via 172.16.216.2 dev ens33 169.254.0.0/16 dev ens33 scope link metric 1002 172.16.216.0/24 dev ens33 proto kernel scope link src 172.16.216.188 [root@~]# ip route | while read p; do ip route change $p initrwnd 10; done [root@~]# ip route default via 172.16.216.2 dev ens33 initrwnd 10 169.254.0.0/16 dev ens33 scope link metric 1002 initrwnd 10 172.16.216.0/24 dev ens33 proto kernel scope link src 172.16.216.188 initrwnd 10 # 一些系统的rwnd值: # Linux 2.6.32 3*MSS (usually 4380) # Linux 3.0.0 10*MSS (usually 14600) # Windows NT 6.1 (Windows 7 or Server 2008 R2) 8192 ^ 2
优化 tcp time_wait ,减少time_wait 状态的连接。主动关闭的一方会出现time_wait状态。 time_wait 状态的连接要等待2个 MSL 的时间才会 close,会占用资源,尽量避免连接进入 time_wait 状态。linux 里 MSL一般是30秒,2 个MSL 是1分钟,这个数值是硬编码在内核中的,除非重新编译内核,否则没法修改。注:MSL最长报文生命周期:Maximum Segment Lifetime,MSL 。 修改 fin_wait2 的值,减少 fin_wait2 的等待时间,超时以后会回收连接。 开启长连接:绝大多是浏览器在开启长连接的情况下,接收到服务器断开连接的fin以后,会恢复一个 ack;而不会不发送自己这一端的 fin ,这样服务器一端就会等待 fin_timeout 时间后,回收连接。 若不开启长连接,服务器端关闭链接以后,链接的状态会从 fin_wait2 转换到 time_wait 。 还可以考虑促使客户端关闭链接,配置 keepalive_timeout 20s 10s; (nginx 配置),使客户端的超时小于服务器端,浏览器会先关闭链接,这样time_wait 状态就会在客户端,不过通过实验看出只有火狐浏览器支持,狐火浏览器会识别 Keep-Alive: timeout=time 这个参数,而别的浏览器不会。 不要设置回收 recycle=1 和 重用 reuse=1,NAT模式下会造成连接失败( SYN 包不会被响应) time_wait 状态的连接被重用(reuse)的条件是如下2个之一: 1)初始序列号比time_wait状态的老连接最末的序列号大。 2)如果使用时间戳,那么新到来的连接的时间戳比老连接的时间戳大。 tcp_tw_reuse和tcp_tw_recycle要生效,必须 tcp_timestamps 是开启的,默认也是开启的。 参数优化 net.ipv4.tcp_max_syn_backlog = 1024 #SYN队列的长度,默认是1024,加大队列到8192或更大,可缓存更多等待的网络连接。 net.ipv4.tcp_max_tw_buckets = 180000 #保存 TIME_WAIT 状态的套接字的最大数量,一旦超过这个数,TIME_WAIT套接字将立刻被清除,并发出警告。 net.ipv4.ip_local_port_range = 1024 65535 # 向外连接的端口范围。缺省值:32768到61000,可以扩大 1024 到 65535。 net.ipv4.tcp_syncookies = 1 #开启SYN Cookies,SYN等待队列溢出时,使用cookies来处理,可防范少量SYN攻击。 net.ipv4.tcp_retries2 = 15 #TCP失败重传的次数 ,默认15 ,可以调小一些,例如5。 还可以配置用于 TCP/IP 链接所使用的内存,配置总内存的话,单位是“页” ,具体的一个页的大小可以通过 getconf PAGE_SIZE 这个命令获取;读写所占用的内存单位是字节。
[root@~]# getconf PAGE_SIZE 4096
总内存 net.ipv4.tcp_mem = 93408 124544 186816 写(缓冲) net.ipv4.tcp_wmem = 4096 16384 3985408 读(缓存) net.ipv4.tcp_rmem = 4096 87380 3985408
[root@~]# cd /proc/sys/net/ipv4 [root@ipv4]# cat tcp_fin_timeout 60 [root@~]# sysctl -a |grep timestamps net.ipv4.tcp_timestamps = 1
initcwnd
ip-sysctl
TLS 协议优化
[root@~]# openssl s_client -connect openssl.org:443 -status |grep -i ocsp depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3 verify error:num=20:unable to get local issuer certificate OCSP response: OCSP Response Data: OCSP Response Status: successful (0x0) Response Type: Basic OCSP Response
3. 会话恢复
TLS理解两种类型的握手:完整握手和简短握手。理论上完整握手只会在客户端与服务器建立TLS会话(TLS session)的时候进行一次。后续的连接,双方使用简短握手恢复之前协商的会话。简短握手因为不需要密钥交换与密钥生成等操作,所以会更快,并且少一次往返时间。
4.TLS的纪录协议造成的在网络传输中的额外开销
5.对称加密对CPU资源的消耗
加密操作有明显的CPU成本,成本由加密算法、加密模式和完整性校验算法三者决定。
6. TLS 记录的缓存延迟
TLS记录是TLS发送和接收数据的最小单位。TLS记录的大小与下一层TCP包的大小并不匹配,一个全尺寸的TLS记录16 KB需要被拆分成许多小的TCP包(大约12个),通常每个小于1.5 KB(1.3KB)。整个TLS记录被分成小的TCP包后,各个小包会陆续到达,但在全部到齐之前是无法进行解密处理的。这是因为TLS记录同样是数据解密和完整性检验的最小单位。缓存延迟有时可能会比较大。 虽然通过TCP协议可以把丢失和延迟的数据包恢复,但仍然需要消耗一次往返。每一次额外的往返对于整个TLS记录都意味着延迟。 初始拥塞窗口另一个触发额外往返的延迟是在连接初期发送大量数据导致初始拥塞窗口溢出。一旦拥塞窗口满了,发送端必须等待响应(1次往返),等到拥塞窗口增加再发送更多数据。 如果Web服务器支持TLS记录调整,就应该考虑将默认值(16 KB这么大的数值)改成更为合理的值,调整这个值由部署的密码套件和相应的传输开销决定,一般情况下设置成4 KB。如果将TLS记录大小设置为与TCP/IP包准确匹配,那就设置成1400字节左右,然后通过观察数据包逐步调整。IP报文理论上最大是65535个字节,是很大的,但是由于IP分片效果很不好,所以TCP在三次握手中互相得知对方的MSS(MTU减IP头部),不给IP层很大块的数据,避免IP数据报分片 例如,数据链路层最大传输单元(maximum transfer unit,MTU)是1500字节,那么可以预见: 1,500 bytes MTU 去除额外开销,所传数据 1379 —1419 bytes 。 -20 bytes IPv4 herder | - 40 bytes IPv6 header - 32 bytes TCP header TCP 头部 最小是20字节可拓展的是40字节,最大为60字节 - 29 bytes TLS record | - 49 bytes TLS record MSS 是1460 bytes :1460 - 32 - 29|49 = 1379 — 1399 bytes 首先MTU的值是变化的。虽然多数客户端继承以太网1500字节的限制,但也有一些协议支持更大的数据。比如,巨型帧(jumbo frame)允许多达9000字节。还有就是使用IPv4和IPv6(IPv4头是20字节,IPv6头是40字节)计算会略有不同,所密码套件的变化也会影响这个数值。 另一个问题是减小TLS记录的大小会增加传输开销,也就是吞吐量会下降。如果将TLS记录长度调大(最大16K),那么由于是加密的数据,得要所有的数据(所有的IP包)都到齐了,才会顺利的解密出明文,等待的时间会较长,吞吐率是上去了,响应的实时性就下降了。nginx上也有配置这个值的选项,只是不能动态调整。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~