Nginx常見異常整理,幫你快速定位

來自公衆號:運維研習社
作者:運維研習社

提示:文章前面部分是關於Nginx下https連接curl請求被reset的處理經歷,不想看可以直接跳到最後看Nginx快速定位異常,建議收藏!

問題描述

網站上線後,添加了https證書,瀏覽器訪問正常,通過curl請求,請求被reset,如上圖

一路艱難

先curl請求同域名下http的url,返回正常,說明兩邊起碼80端口網絡正常

接着curl請求網站同服務器下其他https域名,返回正常,說明兩邊443端口網絡正常

難道是證書問題?查看證書未到期,通過myssl.com查詢證書詳情,沒有問題

懷疑加密套件配置文件,添加兼容性更高的加密套件後嘗試,依然無果

附兼容性加密套件

"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分析

從發起請求到reset,總過16個包,看到是兩端握手完成,發起數據傳輸之後,開始傳輸數據的第一個確認包就被reset了,百思不得其解

難道是客戶端發送的數據太大,nginx的buffer不夠?

修改了nginx關於client的相關設置如下:

client_header_buffer_size 64k;

large_client_header_buffers 4 64k;

client_body_buffer_size 20m;

keepalive_timeout 120;

因爲從抓包看,還沒到fastcgi部分,所以不修改關於fastcgi的buffer部分配置

修改後結果仍然一樣,有點方了

雖然知道應該和證書關係不大,但是還是決定更換一個證書看看,因爲之前是RSA的證書,那我換個ECC的證書試試(推薦七牛雲SSL證書申請,可以選擇ECC證書)

換過之後有新的發現

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

無法與對等體安全通信:無通用加密算法

問題沒解決,還出來新問題了,猜測ECC算法兼容性問題,通過一番google之後,瞭解到如下信息

原來Redhat/CentOS服務器上curl默認是使用NSS庫的,而在這兩個系統上curl默認是禁用ECC加密的,雖然服務端加密套件支持ECC,但是客戶端不支持,所以請求失敗,需要客戶端curl通過指定加密套件來請求

curl --ciphers ecdhe_rsa_aes_128_gcm_sha_256 ...

指定加密套件後,又回到起點,仍然是原來的錯誤,看來和證書沒有關係

柳暗花明

沒辦法,仔細對比了其他網站的nginx配置,沒什麼不一樣,只是沒有配ssl_session_cache,以我對該參數的瞭解,該參數只是作爲ssl優化的一個配置,起到緩存的作用,減少握手次數,但是現在已經“窮途末路"了,先配上再說

萬萬沒想到,好了

抑制着想要喫涮羊肉的心情,又去nginx官網查了下ssl_session_cache參數的解釋

總結如下:

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了,於是我再次抓包對比並和之前的做對比

在數據傳輸之前,除了沒有做Server Key Exchange外,其他沒有任何不同

(reset的連接過程中,多了Server Key Exchange),通過google查詢,拜讀了大神的文章《Winreshark抓包理解HTTPS請求流程》瞭解到,密鑰交換階段,這個步驟是可選步驟,對 Certificate 階段的補充,只有在這幾個場景存在:

  • 協商採用了RSA加密,但是服務端證書沒有提供RSA公鑰

  • 協商採用了DH(EC Diffie-Hellman)加密,但是服務端證書沒有提供DH參數

  • 協商採用了fortezza_kea加密,但是服務端證書沒有提供參數

可以從包裏看到,是協商使用Diffie-Hellman算法

分析到這裏,我仍然不知道爲什麼ssl_session_cache參數會影響到curl的請求,無奈只能這樣了,這裏有大神瞭解的,請留言告知我,感激涕零

下面整理了nginx日誌中常見的error日誌

Nginx快速定位異常

"upstream prematurely(過早的) closed connection"

請求uri的時候出現的異常,是由於upstream還未返回應答給用戶時用戶斷掉連接造成的,對系統沒有影響,可以忽略

"recv() failed (104: Connection reset by peer)"

(1)服務器的併發連接數超過了其承載量,服務器會將其中一些連接Down掉;

(2)客戶關掉了瀏覽器,而服務器還在給客戶端發送數據;

(3)瀏覽器端按了Stop

"(111: Connection refused) while connecting to upstream"

用戶在連接時,若遇到後端upstream掛掉或者不通,會收到該錯誤

"(111: Connection refused) while reading response header from upstream"

用戶在連接成功後讀取數據時,若遇到後端upstream掛掉或者不通,會收到該錯誤

"(111: Connection refused) while sending request to upstream"

Nginx和upstream連接成功後發送數據時,若遇到後端upstream掛掉或者不通,會收到該錯誤

"(110: Connection timed out) while connecting to upstream"

nginx連接後面的upstream時超時

"(110: Connection timed out) while reading upstream"

nginx讀取來自upstream的響應時超時

"(110: Connection timed out) while reading response header from upstream"

nginx讀取來自upstream的響應頭時超時

"(110: Connection timed out) while reading upstream"

nginx讀取來自upstream的響應時超時

"(104: Connection reset by peer) while connecting to upstream"

upstream發送了RST,將連接重置

"upstream sent invalid header while reading response header from upstream"

upstream發送的響應頭無效

"upstream sent no valid HTTP/1.0 header while reading response header from upstream"

upstream發送的響應頭無效

"client intended to send too large body"

用於設置允許接受的客戶端請求內容的最大值,默認值是1M,client發送的body超過了設置值

"reopening logs"

用戶發送kill -USR1命令

"gracefully shutting down"

用戶發送kill -WINCH命令

"no servers are inside upstream"

upstream下未配置server

"no live upstreams while connecting to upstream"

upstream下的server全都掛了

"SSL_do_handshake() failed"

SSL握手失敗

"ngx_slab_alloc() failed: no memory in SSL session shared cache"

ssl_session_cache大小不夠等原因造成

"could not add new SSL session to the session cache while SSL handshaking"

ssl_session_cache大小不夠等原因造成

參考連接:https://blog.csdn.net/firefile/article/details/80537053

小知識

.tcpdump抓包可以,分析包還是得用wireshark

.ECC證書要比RSA證書更小,加解密更快,推薦

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章