这些 Nginx 常见异常,帮你快速定位故障

新闻 系统运维
文章前面部分是关于 nginx 下 https 连接 curl 请求被 reset 的处理经历,后部分是nginx快速定位异常。

  提示:文章前面部分是关于 nginx 下 https 连接 curl 请求被 reset 的处理经历,不想看可以直接跳到最后看nginx快速定位异常,建议收藏!

这些 Nginx 常见异常,帮你快速定位故障

问题描述

网站上线后,添加了https证书,浏览器访问正常,通过curl请求,请求被reset,如上图。

一路艰难

先 curl 请求同域名下http的url,返回正常,说明两边起码80端口网络正常

接着curl请求网站同服务器下其他https域名,返回正常,说明两边443端口网络正常

难道是证书问题?查看证书未到期,通过myssl.com查询证书详情,没有问题。

怀疑加密套件配置文件,添加兼容性更高的加密套件后尝试,依然无果

附兼容性加密套件:

  1. "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4" 

仍然无果后,决定tcpdump两边抓包,用wireshark分析

这些 Nginx 常见异常,帮你快速定位故障

从发起请求到 reset,总过16个包,看到是两端握手完成,发起数据传输之后,开始传输数据的第一个确认包就被 reset 了,百思不得其解

难道是客户端发送的数据太大,nginx 的 buffer 不够?

修改了nginx关于client的相关设置如下:

  1. client_header_buffer_size 64k; 
  2. large_client_header_buffers 4 64k; 
  3. client_body_buffer_size 20m; 
  4. keepalive_timeout 120

因为从抓包看,还没到fastcgi部分,所以不修改关于fastcgi的buffer部分配置

修改后结果仍然一样,有点方了

[[286005]]

虽然知道应该和证书关系不大,但是还是决定更换一个证书看看,因为之前是RSA的证书,那我换个ECC的证书试试(推荐七牛云SSL证书申请,可以选择ECC证书)

换过之后有新的发现

  1. curl: (35) Cannot communicate securely with peer: no common encryption algorithm(s). 

无法与对等体安全通信:无通用加密算法

问题没解决,还出来新问题了,猜测ECC算法兼容性问题,通过一番google之后,了解到如下信息:

原来Redhat/CentOS服务器上curl默认是使用NSS库的,而在这两个系统上curl默认是禁用ECC加密的,虽然服务端加密套件支持ECC,但是客户端不支持,所以请求失败,需要客户端curl通过指定加密套件来请求

  1. curl --ciphers ecdhe_rsa_aes_128_gcm_sha_256 ... 

指定加密套件后,又回到起点,仍然是原来的错误,看来和证书没有关系

柳暗花明

没办法,仔细对比了其他网站的nginx配置,没什么不一样,只是没有配ssl_session_cache,以我对该参数的了解,该参数只是作为ssl优化的一个配置,起到缓存的作用,减少握手次数,但是现在已经“穷途末路”了,先配上再说

万万没想到,好了

[[286006]]

抑制着想要吃涮羊肉的心情,又去nginx官网查了下ssl_session_cache参数的解释

这些 Nginx 常见异常,帮你快速定位故障

总结如下:

ssl_session_cache有4个可选参数

  • off

严禁使用session缓存:nginx明确告诉客户端session可能不会被重用

  • none

session缓存的使用被禁止:nginx告诉客户端session可能会被重用,但实际上并不会将session参数存储在缓存中

  • builtin

在OpenSSL中构建的缓存;仅由一个工作进程使用。缓存大小在session中指定。如果没有给出大小,则等于20480个会话。使用内置高速缓存可能导致内存碎片

  • shared

所有工作进程之间共享缓存。缓存大小以字节为单位指定;一兆字节可以存储大约4000个session。每个共享缓存都应该有一个任意名称。具有相同名称的缓存可以用于多个虚拟服务器

反正就是,你要做缓存的话,就两个参数,builtin和shared,而且这两个参数可以同时开启,但是建议只使用shared,性能要更高一些

但是看完我仍然理解不了,为什么加了这个参数,curl就不报reset了,于是我再次抓包对比并和之前的做对比

这些 Nginx 常见异常,帮你快速定位故障

这些 Nginx 常见异常,帮你快速定位故障

在数据传输之前,除了没有做Server Key Exchange外,其他没有任何不同

(reset的连接过程中,多了Server Key Exchange),通过google查询,拜读了大神的文章《Winreshark抓包理解HTTPS请求流程》了解到,密钥交换阶段,这个步骤是可选步骤,对 Certificate 阶段的补充,只有在这几个场景存在:

  • 协商采用了RSA加密,但是服务端证书没有提供RSA公钥
  • 协商采用了DH(EC Diffie-Hellman)加密,但是服务端证书没有提供DH参数
  • 协商采用了fortezza_kea加密,但是服务端证书没有提供参数

这些 Nginx 常见异常,帮你快速定位故障

可以从包里看到,是协商使用Diffie-Hellman算法

分析到这里,我仍然不知道为什么ssl_session_cache参数会影响到curl的请求,无奈只能这样了,这里有大神了解的,请留言告知我,感激涕零。

下面整理了nginx日志中常见的 error 日志

1.”upstream prematurely(过早的) closed connection”

请求uri的时候出现的异常,是由于upstream还未返回应答给用户时用户断掉连接造成的,对系统没有影响,可以忽略

2.”recv() failed (104: Connection reset by peer)”

(1)服务器的并发连接数超过了其承载量,服务器会将其中一些连接Down掉;

(2)客户关掉了浏览器,而服务器还在给客户端发送数据;

(3)浏览器端按了Stop

3.”(111: Connection refused) while connecting to upstream”

用户在连接时,若遇到后端upstream挂掉或者不通,会收到该错误

4.”(111: Connection refused) while reading response header from upstream”

用户在连接成功后读取数据时,若遇到后端upstream挂掉或者不通,会收到该错误

5.”(111: Connection refused) while sending request to upstream”

Nginx和upstream连接成功后发送数据时,若遇到后端upstream挂掉或者不通,会收到该错误

6.”(110: Connection timed out) while connecting to upstream”

nginx连接后面的upstream时超时

7.”(110: Connection timed out) while reading upstream”

nginx读取来自upstream的响应时超时

8.”(110: Connection timed out) while reading response header from upstream”

nginx读取来自upstream的响应头时超时

9.”(110: Connection timed out) while reading upstream”

nginx读取来自upstream的响应时超时

10.”(104: Connection reset by peer) while connecting to upstream”

upstream发送了RST,将连接重置

11.”upstream sent invalid header while reading response header from upstream”

upstream发送的响应头无效

12.”upstream sent no valid HTTP/1.0 header while reading response header from upstream”

upstream发送的响应头无效

13.”client intended to send too large body”

用于设置允许接受的客户端请求内容的最大值,默认值是1M,client发送的body超过了设置值

14.”reopening logs”

用户发送kill  -USR1命令

15.”gracefully shutting down”

用户发送kill  -WINCH命令

16.”no servers are inside upstream”

upstream下未配置server

17.”no live upstreams while connecting to upstream”

upstream下的server全都挂了

18.”SSL_do_handshake() failed”

SSL握手失败

19.”ngx_slab_alloc() failed: no memory in SSL session shared cache”

ssl_session_cache大小不够等原因造成

20.”could not add new SSL session to the session cache while SSL handshaking”

ssl_session_cache大小不够等原因造成

 

 

 

 

责任编辑:张燕妮 来源: 高效运维
相关推荐

2010-01-04 17:45:51

交换机故障

2009-12-25 10:20:24

ADSL接入网设备

2018-06-27 09:51:17

2015-01-09 10:01:50

Spring MVC

2010-04-22 18:09:38

Aix系统

2011-03-14 09:35:22

2010-11-02 09:53:57

2019-11-15 14:14:13

Python开发BaseExcepti

2011-12-22 10:18:43

美信云网管

2011-08-18 17:16:26

2022-09-20 09:54:35

运维AIOps

2011-06-15 13:20:56

QT Creator 升级

2021-05-20 08:00:00

代码开发工具

2022-01-23 14:14:11

AI人工智能

2020-04-19 17:23:55

混合云云计算

2015-07-30 09:56:48

2010-01-14 16:48:29

交换机故障

2020-03-23 10:51:40

面试技巧技术

2014-06-17 09:51:57

Docker

2010-01-06 09:56:22

点赞
收藏

51CTO技术栈公众号