抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >


Nginx 配置

Nginx 基础配置 安全性配置

Nginx 配置 error_page 404 500 等自定义的错误页面

  • 1. 创建自己的 404.html 页面

  • 2. 更改 nginx.conf 在 http 定义区域加入:

http{
...
fastcgi_intercept_errors on;
...
}
  • 3. 更改 nginx.conf (或单独网站配置文件) 中在 server 区域加入:
server{
...
error_page 400 401 402 403 404 405 408 410 412 413 414 415 500 501 502 503 504 506 /404.html;
location = /404.html {
root /alidata/www/phpwind/error;
}
...
}
  • 4. 更改后重启 nginx, 测试 nginx.conf 正确性:
    nginx -t
  • 5.502 等错误可以用同样的方法来配置。
server{
...
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /alidata/www/phpwind/error;
}
...
}

Nginx 隐藏版本号的安全性与方法

隐藏原因:Nginx 某些版本有漏洞,暴露出来容易被攻击者利用,隐藏起来更安全

隐藏版本号

nginx.conf 中去掉下面注释,或者添加这一行

http{
...
server_tokens off
...
}

如果是转发给 php-fpm ,需要编辑 fastcgi.conf,一般在 nginx.conf 同层
找到:

fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;

改为:

fastcgi_param SERVER_SOFTWARE nginx;

编译源码返回自定义的 server

修改 src/http/ngx_http_header_filter_module.c 中的 48 行

static char ngx_http_server_string[] = "Server: nginx" CRLF;

把其中的 nginx 改为我们自己想要的文字即可,笔者就改为了 GFW.

修改 src/core/nginx.h 定位到 13-14 行

#define nginx_version      2000000
#define NGINX_VERSION "2.0"
#define NGINX_VER "GFW/" NGINX_VERSION

Server 返回的就是常量 NGINX_VER

重新编译

make && make install

控制缓冲区溢出攻击

编辑 nginx.conf,为所有客户端设置缓冲区的大小限制。

编辑和设置所有客户端缓冲区的大小限制如下:

http {
...
## Start: Size Limits & Buffer Overflows ##
client_body_buffer_size 1K;
client_header_buffer_size 1k;
client_max_body_size 1k;
large_client_header_buffers 2 1k;
## END: Size Limits & Buffer Overflows ##
...
}

解释:

  • 1、client_body_buffer_size 1k-(默认 8k 或 16k)这个指令可以指定连接请求实体的缓冲区大小。如果连接请求超过缓存区指定的值,那么这些请求实体的整体或部分将尝试写入一个临时文件。

  • 2、client_header_buffer_size 1k - 指令指定客户端请求头部的缓冲区大小。绝大多数情况下一个请求头不会大于 1k,不过如果有来自于 wap 客户端的较大的 cookie 它可能会大于 1k,Nginx 将分配给它一个更大的缓冲区,这个值可以在 large_client_header_buffers 里面设置。

  • 3、client_max_body_size 1k - 指令指定允许客户端连接的最大请求实体大小,它出现在请求头部的 Content-Length 字段。
    如果请求大于指定的值,客户端将收到一个”Request Entity Too Large” (413) 错误。记住,浏览器并不知道怎样显示这个错误。

  • 4、large_client_header_buffers - 指定客户端一些比较大的请求头使用的缓冲区数量和大小。请求字段不能大于一个缓冲区大小,如果客户端发送一个比较大的头,nginx 将返回”Request URI too large” (414)

    同样,请求的头部最长字段不能大于一个缓冲区,否则服务器将返回”Bad request” (400)。缓冲区只在需求时分开。默认一个缓冲区大小为操作系统中分页文件大小,通常是 4k 或 8k,如果一个连接请求最终将状态转换为 keep-alive,它所占用的缓冲区将被释放。

你还需要控制超时来提高服务器性能并与客户端断开连接。按照如下编辑:

http {
...
## Start: Timeouts ##
client_body_timeout 10;
client_header_timeout 10;
keepalive_timeout 5 5;
send_timeout 10;
## End: Timeouts ##
...
}
  • 1、client_body_timeout 10;- 指令指定读取请求实体的超时时间。这里的超时是指一个请求实体没有进入读取步骤,如果连接超过这个时间而客户端没有任何响应,Nginx 将返回一个”Request time out” (408) 错误。

  • 2、client_header_timeout 10;- 指令指定读取客户端请求头标题的超时时间。这里的超时是指一个请求头没有进入读取步骤,如果连接超过这个时间而客户端没有任何响应,Nginx 将返回一个”Request time out” (408) 错误。

  • 3、keepalive_timeout 5 5; – 参数的第一个值指定了客户端与服务器长连接的超时时间,超过这个时间,服务器将关闭连接。参数的第二个值(可选)指定了应答头中 Keep-Alive: timeout=time 的 time 值,这个值可以使一些浏览器知道什么时候关闭连接,以便服务器不用重复关闭,如果不指定这个参数,nginx 不会在应答头中发送 Keep-Alive 信息。(但这并不是指怎样将一个连接 “Keep-Alive”)参数的这两个值可以不相同。

  • 4、send_timeout 10; 指令指定了发送给客户端应答后的超时时间,Timeout 是指没有进入完整 established 状态,只完成了两次握手,如果超过这个时间客户端没有任何响应,nginx 将关闭连接。

限制可用的请求方法

GET 和 POST 是互联网上最常用的方法。 Web 服务器的方法被定义在 RFC 2616。如果 Web 服务器不要求启用所有可用的方法,它们应该被禁用。下面的指令将过滤只允许 GET,HEAD 和 POST 方法:

server {
...
## Only allow these request methods ##
if ($request_method !~ ^(GET|HEAD|POST)$ ) {
return 444;
}
## Do not accept DELETE, SEARCH and other methods ##
...
}

更多关于 HTTP 方法的介绍

GET 方法是用来请求,如文件 https://www.centos.bz/index.php。
HEAD 方法是一样的,除非该服务器的 GET 请求无法返回消息体。
POST 方法可能涉及到很多东西,如储存或更新数据,或订购产品,或通过提交表单发送电子邮件。这通常是使用服务器端处理,如 PHP,Perl 和 Python 等脚本。如果你要上传的文件和在服务器处理数据,你必须使用这个方法。

拒绝一些 User-Agents

你可以很容易地阻止 User-Agents, 如扫描器,机器人以及滥用你服务器的垃圾邮件发送者。
Nginx 的 444 状态比较特殊,如果返回 444 那么客户端将不会收到服务端返回的信息,就像是网站无法连接一样

server {
...
## Block download agents ##
if ($http_user_agent ~* LWP::Simple|BBBike|wget|curl) {
return 444;
}
##
...
}

阻止 Soso 和有道的机器人:

server {
...
## Block some robots ##
if ($http_user_agent ~* Sosospider|YodaoBot) {
return 403;
}
##
...
}

Header 头设置

通过以下设置可有效防止 XSS 攻击

add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";

X-Frame-Options: 响应头表示是否允许浏览器加载 frame 等属性,有三个配置 DENY 禁止任何网页被嵌入,SAMEORIGIN 只允许本网站的嵌套,ALLOW-FROM 允许指定地址的嵌套

X-XSS-Protection: 表示启用 XSS 过滤(禁用过滤为 X-XSS-Protection: 0),mode=block 表示若检查到 XSS 攻击则停止渲染页面

X-Content-Type-Options: 响应头用来指定浏览器对未指定或错误指定 Content-Type 资源真正类型的猜测行为,nosniff 表示不允许任何猜测

在通常的请求响应中,浏览器会根据 Content-Type 来分辨响应的类型,但当响应类型未指定或错误指定时,浏览会尝试启用 MIME-sniffing 来猜测资源的响应类型,这是非常危险的

例如一个.jpg 的图片文件被恶意嵌入了可执行的 js 代码,在开启资源类型猜测的情况下,浏览器将执行嵌入的 js 代码,可能会有意想不到的后果

另外还有几个关于请求头的安全配置需要注意

Content-Security-Policy: 定义页面可以加载哪些资源,

add_header Content-Security-Policy "default-src 'self'";

上边的配置会限制所有的外部资源,都只能从当前域名加载,其中 default-src 定义针对所有类型资源的默认加载策略,self 允许来自相同来源的内容

Strict-Transport-Security: 会告诉浏览器用 HTTPS 协议代替 HTTP 来访问目标站点

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";

上边的配置表示当用户第一次访问后,会返回一个包含了 Strict-Transport-Security 响应头的字段,这个字段会告诉浏览器,在接下来的 31536000 秒内,当前网站的所有请求都使用 https 协议访问,参数 includeSubDomains 是可选的,表示所有子域名也将采用同样的规则

经过多层 CDN 之后取得原始用户的 IP 地址,nginx 配置根据用户的真实 IP 做连接限制

http {
...
##############
map $http_x_forwarded_for $clientRealIp {
## 没有通过代理,直接用 remote_addr
"" $remote_addr;
## 用正则匹配,从 x_forwarded_for 中取得用户的原始IP
## 例如 X-Forwarded-For: 202.123.123.11, 208.22.22.234, 192.168.2.100,...
## 这里第一个 202.123.123.11 是用户的真实 IP,后面其它都是经过的 CDN 服务器
~^(?P<firstAddr>[0-9\.]+),?.*$ $firstAddr;
}

## 通过 map 指令,我们为 nginx 创建了一个变量 $clientRealIp ,这个就是 原始用户的真实 IP 地址,
## 不论用户是直接访问,还是通过一串 CDN 之后的访问,我们都能取得正确的原始IP地址
#################
## 针对原始用户 IP 地址做限制
limit_conn_zone $clientRealIp zone=TotalConnLimitZone:20m ;
limit_conn TotalConnLimitZone 50;
limit_conn_log_level notice;

## 针对原始用户 IP 地址做限制
limit_req_zone $clientRealIp zone=ConnLimitZone:20m rate=10r/s;
limit_req zone=ConnLimitZone burst=10 nodelay;
limit_req_log_level notice;
######################
...
}

nginx 日志按天保存

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '

                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
log_format  main  '$remote_addr - $remote_user [$time_iso8601] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

将原来的 time_local 修改为 time_iso8601,该格式日期为 “2017-01-19T09:10:52+08:00”,也可以其他格式,看个人习惯

注意层次关系,这段脚本一定要加到 server 配置内部,且 if 要在 access_log 前面,否则 set 的变量将无法引用

server{
...
if ($time_iso8601 ~ '(\d{4}-\d{2}-\d{2})') {
                set $tttt $1;
        }
        access_log  logs/access-$tttt.log  main;
...
}

按 yyyy-mm-dd 格式截取字符串,写入指定日志文件中

执行 nginx -s reload 后则配置生效

http {
....
log_format main '$remote_addr - $remote_user [$time_iso8601] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
server {
if ($time_iso8601 ~ '(\d{4}-\d{2}-\d{2})') {
set $tttt $1;
}
access_log logs/$tttt.access.log main;
....
}
....
}

推荐阅读
Nginx隐藏版本号信息 Nginx隐藏版本号信息 自建https证书 自建https证书 大数据处理技术-Hadoop-MapReduce的运行机制 大数据处理技术-Hadoop-MapReduce的运行机制 大数据处理技术-HDFS 的架构 大数据处理技术-HDFS 的架构 kafka的管理使用 kafka的管理使用 Package Manager Proxy Settings Package Manager Proxy Settings

留言区

Are You A Robot?