MHuiG

「看庭前花开花落,望天上云卷云舒」

Nginx 配置

# 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;
            ....
        }
        ....
    }

Linux安装PHP-EXIF扩展模块

PHP-EXIF 扩展 Linux 安装 PHP-EXIF 扩展模块 您可以使用 exif 相关的函数从文件头读取数码相机拍摄的 JPEG 和 TIFF 格式的图像文件元数据。 安装编...

Nginx隐藏版本号信息

Nginx 隐藏版本号信息 Nginx 隐藏版本号信息 当我们使用 apt 或者其他包管理工具安装完 Nginx 之后，访问网站时 Header 里面会默认携带 Nginx 的版本号信...

留言区

Notes
CentOS
本文目录
Are You A Robot?