nginx配置之安全篇

[TOC]

使用最新的版本

find / -name nginx                  # 找到nginx安装目录

/usr/local/nginx/sbin/nginx -V      # 查看ngxin版本

禁止目录浏览/隐藏版本信息

  • 由于某些 Nginx 漏洞只存在于特定的版本,隐藏版本号可以提高安全性
  • 一些 WEB 语言或框架默认输出的 X-Powered-By 也会泄露网站信息,如果部署上用到了 Nginx 的反向代理,则建议隐藏Nginx后端服务响应头中的版本信息,比如 X-Powered-By: PHP/5.4.43
http {
    autoindex off;                      # 禁止目录浏览
    server_tokens off;                  # 隐藏nginx版本信息,提高安全性,但并不会加快nginx的执行速度
    proxy_hide_header X-Powered-By;     # 隐藏proxy反向代理的后端主机头信息
    proxy_hide_header Server;
}
  • 验证效果
[root@localhost]# curl -s -I http://127.0.0.1 | grep Server  #整改前
Server: nginx/1.25.0

[root@localhost]# curl -s -I http://127.0.0.1 | grep Server  #整改后
Server: nginx

限制功能

限制HTTP请求方法

  • 对于一般的网站和应用程序,只用允许 GET、POST、HEAD 这3种请求即可,其他请求方法直接返回 444 空响应
http {
    #.其他省略...
    server {
        #.其他省略...
        location / {
            if ($request_method !~ ^(GET|HEAD|POST)$ ) {
                return 444;         # HTTP 444 响应指空响应
            }
        }
    }
}

限制IP访问

  • 若是内部业务或无需对外开放的站点,建议限制某些IP地址的客户端访问
  • 规则按照顺序依次检测,直到匹配到第一条规则。 如下示例只允许 192.168.1.0/2410.1.0.0/16 访问,但 192.168.1.1 除外。
http {
    #.其他省略...
    server {
        #.其他省略...
        location / {
            deny 192.168.1.1;           # 拒绝ip
            allow 192.168.1.0/24;       # 允许ip
            allow 10.1.0.0/16;          # 允许ip
            deny all;                   # 拒绝其他所有ip
        }
    }
}

限制并发和速度

nginx限制IP的连接和并发分别有两个模块:

  • limit_req_zone 用来限制单位时间内的请求数,即速率限制,采用的漏桶算法 "leaky bucket"
  • limit_req_conn 用来限制同一时间连接数,即并发限制

其中 limit_req_conn 模块可以根据源IP限制单用户并发访问的连接数或连接到该服务的总并发连接数。

注:limit_req 如果请求不需要被延迟,添加 nodelay 参数,服务器会立刻返回503状态码。加上 nodelay之后超过 burst大小的请求就会直接返回503,如果没有该字段会造成大量的tcp连接请求等待。

http {
    #.配置limit_zone(缓存空间)为one
    limit_conn_log_level error;
    limit_conn_status 503;
    limit_conn_zone $binary_remote_addr zone=one:10m;                   # Zone=one:10m 表示设置了名为one的存储区,大小为10m
    limit_conn_zone $server_name zone=perserver:10m;
    limit_req_zone $binary_remote_addr zone=allips:100m rate=10r/s;     # rate=10r/s 表示允许每秒不超过10个请求

    server {
        #.其他省略...
        location / {
            limit_conn one 100;                         # 表示限制每个客户端IP的最大并发连接数100
            limit_conn perserver 1000;                  # 表示该服务提供的总连接数不得超过1000,超过请求的会被拒绝
            limit_req zone=allips burst=5 nodelay;      # 表示最大延迟请求数量不大于5,若请求过多而不需要限制延迟则配置nodelay参数
        }
    }
}

设置超时时间

  • 合理设置timeout可防御DOS攻击
http {
    keepalive_timeout 60;           # TCP长连接存活时间,默认75秒
    client_header_timeout 10;       # 设置请求头header的超时时间
    client_body_timeout 10;         # 设置请求体body的超时时间
    send_timeout 600;               # 指定客户端的响应超时时间
}

自定义缓冲区大小

  • 设置自定义缓存以限制缓冲区溢出攻击
http {
    #.其他省略...
    client_header_buffer_size 4k;       # 设置客户端请求的header头缓冲区大小
    client_body_buffer_size 256k;       # 客户端post的数据先写入client_body_buffer中,若buffer写满会写入临时文件
    client_max_body_size 20m;           # 设置客户端能够上传的文件大小
    large_client_header_buffers 4 32k;  # 对于超过client_header_buffer_size的header将会使用该部分buffer,第一个是个数,第二个是每个buffer的大小
    server_names_hash_bucket_size 128;  # 服务器名字的hash表大小,可选32/64/128
}

注:上述的参数不是最优参数,仅供参考。

账号及权限

配置nginx进程启动账号

  • 创建nginx服务账户(比如 www),并修改站点目录(比如 /data/website)的权限
cat /etc/passwd | grep www || useradd www -s /sbin/nologin
chown -R www.www /data/website
  • 更改nginx默认用户,为nginx服务降权(使用非root跑nginx woker进程)
user www;

配置Nginx账号锁定

  • 执行 passwd -l www 将nginx启动账号进行锁定
  • 执行 passwd -S www 确认账号已锁定
[root@localhost]# passwd -l www
Locking password for user www.
passwd: Success

[root@localhost]# passwd -S www
www LK 2023-06-05 0 99999 7 -1 (Password locked.)

配置nginx配置文件权限

  • 确保NGINX配置文件权限为644,以抵御外来攻击
  • 默认文件为 /usr/local/nginx/conf/nginx.conf
find / -name nginx.conf

chmod 644 /usr/local/nginx/conf/nginx.conf

日志相关

日志设置

  • 通过 log_format 指令自定义请求日志的格式,注:nsfocus 是设置配置文件格式的 alias
  • 在server作用域中配置的access_log,其的优先级比http下的高,如果没有指定log_format则会使用系统默认的combined
http {
    log_format nsfocus '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
    #access_log off                                 # 关闭当前作用域下的访问日志,可加快磁盘io操作
    access_log logs/nginx_access.log nsfocus;       # 设置访问日志的位置和格式
    error_log logs/nginx_error.log crit;            # 设置错误日志的位置和级别

    server {
        #.其他省略...
        # access_log /var/log/nginx_access.log;     # 
        # error_log /var/log/nginx_error.log;       # server作用域的优先级比http下的高
    }
}

使用logrotate切割日志

  • 通过 yum 安装 logrotate 日志服务
yum install -y logrotate
  • 创建一个切割 nginx 的配置文件
cat > /etc/logrotate.d/nginx <<EOF
/usr/local/nginx/logs/*nginx*.log {
  daily
  rotate 7
  minsize 50M
  missingok
  dateext
  compress
  notifempty
  sharedscripts
  postrotate
    [ -e /usr/local/nginx/logs/nginx.pid ] && kill -USR1 `cat /usr/local/nginx/logs/nginx.pid`
  endscript
}
EOF
  • 通常,logrotate 切割时间默认是在每天的3:22
[root@localhost local]# cat /etc/anacrontab | grep START_HOURS_RANGE
START_HOURS_RANGE=3-22

自定义错误信息

  • 在网站访问过程中,经常会遇见各种各样的错误,如找不到访问的页面则会提示 404 Not Found 错误,没有访问权限会提示 403 Forbidden 等,对于普通人而言,这样的提示界面并不友好。
error_page 403 /403.html;               # 指定网站根目录下的页面 403.html, 处理 403 错误 
error_page 404 =200 /404.jpg;           # 更改晌应状态码,产生4O4的时候返回码是200,内容是404.jpg
error_page 500 502 503 504 /50x.html;   # 为某一类的错误设置处理方式

location = /50x.html {                  # 配置location保证可以找到自定义的50x页面
    root /usr/share/nginx/html;
}

合理配置响应头

  • 如果网站是由 Nginx 通过 proxy_pass 把请求反向代理给后端的 IP 和端口,则建议添加如下头部响应:
http {
    #.其他省略...
    server {
        #.其他省略...
        location / {
            add_header Strict-Transport-Security "max-age=31536000";    # 在指定的max-age内,始终通过HTTPS访问本站,即使用户输入HTTP地址也会在本地替换为HTTPS再发送请求
            add_header X-Frame-Options deny;                            # 指定此网页是否允许被iframe嵌套,deny就是不允许任何嵌套发生
            add_header X-Content-Type-Options nosniff;
        }
    }
}

配置防盗链

  • 防盗链简单来说就是应用服务中的一些资源,只有规定的合法的请求才能访问,其他请求不能访问资源(如css,js,img等)
  • valid_referers 指令 server_names 参数:若 referer 中的站点域名和 server_names 中的某个域名匹配,则允许访问
http {
    #.其他省略...
    server {
        #.其他省略...
        location ~* ^.+\.(gif|jpg|png|swf|flv|rar|zip)$ {
            expires 30d;
            valid_referers none blocked server_names *.sqlfans.cn http://localhost;     # 有效的来源
            if ($invalid_referer) {                                                     # 如果无效的来源
                rewrite ^/ http://www.xxx.com/403.html;
                # return 403;
            }
        }
    }
}
  • 验证效果
curl --referer http://wiki.sqlfans.cn -I http://127.0.0.1/logo.png

SSL协议加固

  • 启用 HTTPS 并正确配置了证书,意味着数据传输过程中无法被第三者解密或修改
  • 通过参数 ssl_protocols(没有请添加)禁用TLS 1.0、TLS 1.1(去掉即可),并将其替换为TLS 1.2或更高版本
http {
    server {
        listen 443 ssl;
        #.其他省略...

        ssl_protocols TLSv1.2 TLSv1.3;      # 启用TLSv1.3则要求 OpenSSL版本 >= 1.1.1
        ssl_ciphers HIGH:!aNULL:!MD5;       # 用!号禁用不需要的加密套件
        ssl_prefer_server_ciphers on;
    }
}
Copyright © www.sqlfans.cn 2023 All Right Reserved更新时间: 2023-06-06 15:48:35

results matching ""

    No results matching ""