最近伺服器異常,nginx訪問日誌中出現大量的如下形式的請求:
x23.1x3.21x.xx - - [08/Jun/2012:04:46:39 +0800] "-" 400 0 "-" "-"x23.1x3.21x.xx - - [08/Jun/2012:04:46:39 +0800] "-" 408 0 "-" "-"
每天這種請求大概占請求量的50%左右。
在php代碼中,未定義400的異常,因此可以判定非php拋出。
網上查的出現這種日誌主要有如下原因:
- 要求標頭過長,尤其是在cookie過多的情況下。
- chrome的preconnect技術,會產生大量的如上日誌。
- no Host header sent
1. 要求標頭過長,那麼可以修改nginx的要求標頭參數設定到一個合理的值。
參數:
client_header_buffer_size 64k;large_client_header_buffers 4 32k;
但是事實上一般不會出現這種錯誤,因為nginx資深設定的要求標頭一般夠用。
除非你定義了大量的cookie。
2. chrome preconnect
如果是因為chrome的原因,有個很明顯的特徵:在每個400 0請求之前的請求user-agent='chrome'
而且這個是無解的。
3. no host header sent.
主要是指ip掃描工具,掃描當前機器ip,會產生一個請求,header中無host
如下指令碼,就可以產生:
#!/bin/bashexec 8<>/dev/tcp/openapi.360.cn/443echo -ne "" >&8cat <&8
我們可以通過定義一個default_server來接受所有的ip請求。
server { listen 80 default_server; server_name _; access_log off; location / { deny all; } }
這樣所有的ip請求被拋到default_server中,且關閉了日誌。
這樣這些煩人的"400 0"就不見了
說到這裡,問題就基本解決了。但是還有一項事情要注意:
https伺服器必須加入ssl_certificate, ssl_certificate_key兩個參數
server { listen 443 ssl default_server; server_name _; ssl_certificate /usr/local/nginx/conf/ssl/edward.crt; ssl_certificate_key /usr/local/nginx/conf/ssl/edward.key; access_log off; location / { deny all; }}