最近服务器异常,nginx访问日志中出现大量的如下形式的请求:
每天这种请求大概占请求量的50%左右。 在php代码中,未定义400的异常,因此可以判定非php抛出。
我们可以通过定义一个default_server来接受所有的ip请求。
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/bash
exec 8<>/dev/tcp/openapi.360.cn/443
echo -ne "" >&8
cat <&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;
}
}