[关闭]
@dungan 2018-10-16T09:59:49.000000Z 字数 7160 阅读 95

Nginx

Nginx Web 服务优化

Nginx 基本安全优化

隐藏 Nginx 版本号

  1. http{
  2. ...
  3. server_tokens off;
  4. ...
  5. }

更改 Nginx 默认用户

  1. # 新增一个没有登录权限的用户
  2. [root@VM_0_17_centos ~]# useradd nginx -s /sbin/nologin -M
  3. [root@VM_0_17_centos ~]#
  4. # 修改nginx.conf中的默认用户
  5. user nginx nginx

根据参数优化 Nginx 服务性能

优化 Nginx worker 进程数

尽管常规的做法是将进程数设置cpu核心数或者cpu核心数*2,但进程数除了要和cpu 核心匹配外,还要考虑到内存和IO的问题,最好设置成auto,让系统自动检测,Nginx 有 Master 和 wroker进程之分,Master 进程为管理进程,真正处理请求的是 worker 进程,相关设置位于 main 区块 !

  1. user www www;
  2. worker_processes auto;

绑定不同的进程到不同的 cpu 上

为了避免多个进程有可能跑在某一个CPU或CPU的某一核上,导致 Nginx 进程使用的硬件资源不均,这就需要尽可能分配不同的 nginx 进程给 cpu 处理,大道有效利用硬件多CPU多核的目的,相关设置位于 main 区块!

  1. # 两核
  2. worker_processes 2;
  3. worker_cpu_affinity 10 01
  4. # 四核
  5. worker_processes 4;
  6. worker_cpu_affinity 1000 0100 0010 0001
  7. # 可以看到有几个核心,就有几组数组,配置时保证每位都有一个1

优化 Nginx 的 I/O 模型 和 最大连接数

可供选择的 I/O 模型有『kqueue|rtsig|epoll|poll|select|poll』,关于它们在第一节已经介绍过了!

一般建议选择 epoll 模型,当然 Nginx 默认情况下会自动选择最佳的 IO 模型;
worker_connections 用于设置单个进程最大连接数, 默认是 1024,因此 Nginx能抗住的最大并发连接=worker_processes*worker_connections,进程的最大连接数受系统能够打开的文件数限制,因此还得设置能打开的最大文件描述符数目,相关设置位于 main 区块!

  1. events {
  2. use epoll;
  3. worker_connections 51200;
  4. multi_accept on;
  5. }

配置 Nginx worker 能打开的文件描述符数目

该位于 main 区块

  1. # 第一种:通过命令
  2. ulimit -HSn 51200
  3. # 第二种:修改配置 !
  4. worker_rlimit_nofile 51200;

优化服务器域名的散列表大小

服务器的域名如果太长的话有可能引起错误,如果有长域名的话可以借助指令 server_names_hash_bucket_size,该指令位于 http 区块!

  1. http {
  2. ...
  3. server_names_hash_bucket_size 128;
  4. ...
  5. }

开启高效文件传输

sendfile 指令用于开启文件的高效传输模式,同时将 tcp_nopush 和 tcp_nodelay 两个指令设置为 on,可防止网络及磁盘 I/O 阻塞,这三个指令可放置在区块 http,server,location,if 。

  1. http {
  2. ...
  3. sendfile on;
  4. tcp_nopush on;
  5. tcp_nodelay on;
  6. ...
  7. }

优化 Nginx 连接参数,调整连接超时时间

连接超时是为了避免进行交互的两方,由于长时间接受不到对方的数据而死等的问题,因为建立连接会消耗服务器的资源,所以一定时间内没有得到响应就应该断掉连接,释放资源!

Nginx 的连接和如下几个指令有关

  1. http {
  2. ...
  3. keepalive_timeout 120;
  4. tcp_nodelay on;
  5. client_header_timeout 50;
  6. client_body_timeout 50;
  7. send_timeout 25;
  8. ...
  9. }
  • keepalive_timeout:单位为秒,用来设置客户端连接超过多长时间会被服务端给断掉,在超时时间内如果有持续请求,keep-alive 会复用已经建立的连接,该指令可放置的区块有 http,server,location。
  • tcp_nodelay:当为 on 时内核会缓冲发送给客户端的数据,等待更多的字节组成一个数据包,以能提升 I/O 性能,可放置的区块有 http,server,location。
  • client_header_timeout:单位为秒,用来设置读取客户端请求头数据的超时时间,可放置的区块有 http,server。
  • client_body_timeout:单位为秒,用来设置读取客户端请求体的超时时间,这个时间指的是两次成功的读取操作之间的超时,并非整个等待整个请求体数据的超时时间,可放置的区块有 http,server,location。
  • send_timeout:单位为秒,用来设置发送响应信息到客户端的时间,这个时间指的是两次成功握手后的一个超时,并非请求整个响应数据的超时时间,可放置区块有 http,server,location。

上传文件大小限制

client_max_body_size 用于设置客户端请求体最大大小,客户端在提交数据时请求头一般会携带 Content-Length,一旦超过 client_max_body_size 客户端会收到 413 错误,意思是请求的条目过大,当然如果不想检验客户端的请求体大小,可设为 0,该指令可放置的区块 http,server,location。

  1. http {
  2. client_max_body_size 1024m;
  3. }

gzip 压缩

使用gzip压缩功能,能为节约带宽,加快传输速度,常用于压缩文本,Nginx启用压缩功能依靠 ngx_http_gzip_module 实现,一般需要压缩的内容有:文本,js,html,css,但对于图片视频等二进制文件就没必要压缩了,压缩率低,浪费CPU资源!

光服务器压缩还不行,浏览器也要支持这种功能,浏览器的请求头带还需要带上 Accept-Encoding: gzip

  1. http {
  2. ...
  3. # 是否开启gzip
  4. gzip on;
  5. # 禁用IE6的gzip压缩
  6. gzip_disable "msie6";
  7. # 缓冲区的数量与大小
  8. gzip_buffers 16 8k;
  9. # 压缩级别
  10. gzip_comp_level 6;
  11. # HTTP协议版本
  12. gzip_http_version 1.1;
  13. # 设置超过多少字节才压缩,页面字节数从header头的Content-Length中获取,
  14. # 默认值是0,不管页面多大都进行压缩,建议设置成大于1K,如果小与1K可能会越压越大
  15. gzip_min_length 256;
  16. # 设置对代理的响应数据进行压缩
  17. gzip_proxied any;
  18. # 让前端缓存服务器缓存经过GZIP压缩后的数据
  19. gzip_vary on;
  20. # 压缩类型
  21. gzip_types
  22. text/xml application/xml application/atom+xml application/rss+xml
  23. application/xhtml+xml image/svg+xml
  24. text/javascript application/javascript application/x-javascript
  25. text/x-json application/json application/x-web-app-manifest+json
  26. text/css text/plain text/x-component
  27. font/opentype application/x-font-ttf application/vnd.ms-fontobject
  28. image/x-icon;
  29. ...
  30. }

gzip on;gzip_types xxx; 这两个指令必须设置,其他的可选!

expires 缓存

expires 的功能是缓存用户访问过的静态资源(于图片,css,js),当给这些资源设置一个过期时间后会使这些资源缓存在用户的浏览器,这样用户第一次从服务器获取资源后,第二次再请求时则会从本地访问!

当到了 expires 设置的时间后,浏览器会通过 etag 和 Last-Modified 来判断资源是否有变化进而重新获取资源!

  1. # 缓存这些后缀类型文件 30天
  2. location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
  3. {
  4. expires 30d;
  5. }
  6. # 缓存js和css文件 1小时
  7. location ~ .*\.(js|css)?$
  8. {
  9. expires 1h;
  10. }

Nginx 站点目录及文件 URL 访问控制

限制访问指定文件

  1. localtion ~ ^/static/.*\.(php|php5|sh|py)$ {
  2. deny all;
  3. }

限制指定目录的访问

  1. localtion ~ ^/(images|static) {
  2. deny all;
  3. }
  4. location /admin/ {
  5. return 404;
  6. }

限制 IP 访问

  1. location / {
  2. deny 192.168.1.1;
  3. allow 192.168.1.0/24;
  4. allow 10.1.1.0/16;
  5. allow 2001:0db8::/32;
  6. deny all;
  7. }
  8. location /static/ {
  9. deny 192.168.1.1;
  10. allow all;
  11. }

禁止非法域名解析 ip 到用户服务器

当你使用本机 ip 或 localhost 时,nginx 一般会有一个默认的虚拟主机来响应这种情况的请求,当然你可以禁止使用 ip 来访问默认主机!

  1. # 禁止使用 ip 来访问 nginx 默认主机!
  2. server {
  3. listen 80;
  4. server_name _;
  5. ...
  6. return 501; # 使用 ip 访问网站的用户收到 501 错误!
  7. ...
  8. }
  9. # 禁止恶意域名解析到用户服务器
  10. if ($host !~ ^ www.test.com$)
  11. {
  12. rewrite ^(.*) http://www.test.com/$1 permanent;
  13. }

配置 http 错误状态码页面

由于一般返回给客户端的错误状态码比较丑,而使用指令 error_page 则可以为状态码设置一个比较优雅好看的错误页面,该指令可位于 server,http,location,if 区块中!

  1. server {
  2. ...
  3. server_name _;
  4. root /data/wwwroot/default/;
  5. # /404.html /50x.html 都是相对于 root 目录的
  6. error_page 404 /404.html;
  7. error_page 501 502 /50x.html;
  8. # 重定向到某个远程地址
  9. error_page 501 503 http://www.test.com/error/50x.html;
  10. # 重定向到location
  11. error_page 500 = /50x;
  12. location /50x{
  13. rewrite ^.*$ /50x.html;
  14. # prox_pass http://www.test.com/error/50x.html; # 也可以转发到远程地址
  15. }
  16. ...
  17. }

另附:http 状态码列表

状态码 描述
200 OK 表示请求被服务器正常处理
301 Moved Permanently 永久重定向,表示请求的资源已经永久的搬到了其他位置
302 Found 临时重定向,表示请求的资源临时搬到了其他位置
304 Not Modified 所请求的资源未修改,服务器返回此状态码时,不会返回任何资源,也就是让客户端使用缓存。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源
400 Bad Request 客户端请求的语法错误,服务器无法理解
401 Unauthorized 表示发送的请求需要有HTTP认证信息或者是认证失败了
403 Forbidden 请求成功,但服务器决绝提供资源,例如 『跨域』一类的问题
404 Not Found 服务器找不到客户端请求的资源
500 Internal Server Error 表示服务器内部执行请求的时候出错了,例如 脚本执行出错
502 Bad Gateway 作为网关或者代理工作的服务器请求后端服务时,从后端服务器接收到无效的响应
503 Service Unavailable 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中
504 Gateway Time-out 充当网关或代理的服务器,未及时从远端服务器获取请求

防爬虫

防爬虫本质来说就是阻止某些爬虫UA,IP,或者工具请求你服务器的资源,你要做的就是枚举出它们!

  1. # 禁止Scrapy等工具的抓取
  2. if ($http_user_agent ~* (Scrapy|Curl|HttpClient))
  3. {
  4. return 403;
  5. }
  6. # 禁止指定爬虫UA访问
  7. if ($http_user_agent ~ "FeedDemon|JikeSpider|Indy Library|Alexa Toolbar|AskTbFXTV|AhrefsBot|CrawlDaddy|CoolpadWebkit|Java|Feedly|UniversalFeedParser|ApacheBench|Microsoft URL Control|Swiftbot|ZmEu|oBot|jaunty|Python-urllib|lightDeckReports Bot|YYSpider|DigExt|YisouSpider|HttpClient|MJ12bot|heritrix|EasouSpider|Ezooms|^$" )
  8. {
  9. return 403;
  10. }
  11. # 禁止非GET|HEAD|POST方式的抓取
  12. if ($request_method !~ ^(GET|HEAD|POST)$)
  13. {
  14. return 403;
  15. }
  16. #屏蔽单个IP
  17. #deny 123.45.6.7
  18. #封整个段即从123.0.0.1到123.255.255.254
  19. #deny 123.0.0.0/8
  20. #封IP段即从123.45.0.1到123.45.255.254
  21. #deny 124.45.0.0/16
  22. #封IP段即从123.45.6.1到123.45.6.254
  23. #deny 123.45.6.0/24

控制并发连接数

ngx_http_limit_conn_module 用来限制每个定义的 key 的连接数,key 的类型可以是 ip域名 等,这样就能针对 ip域名 等来进行并发控制!

指令说明

limit_conn_zone key zone=name:size

该指令用于在内存中设置一块空间,key 可以是ip,虚拟主机等nginx全局变量, name是内存区域的名称,size 是内存区域的大小;该指令只能放置在区块 http。

limit_conn zone number

该指令用于控制同一时间给定类型 key 的并发链接数,当同一时间并发连接数大于numer时,部分并发请求会被服务器返回 503 错误;该指令可放置的区块有 http,server!

示例:

  1. http {
  2. # 在内存中找一块10m大小的空间,限制单一ip的并发连接数
  3. limit_conn_zone $binary_remote_addr zone=addr:10m;
  4. # 在内存中找一块10m大小的空间,限制虚拟主机的并发连接数
  5. #limit_conn_zone $server_name zone=perserver:10m;
  6. ...
  7. server {
  8. ...
  9. location /download/ {
  10. limit_conn addr 1; # 同一 IP,同一时间只允许有一个连接
  11. #limit_conn perserver 100; # 同一虚拟主机,同一时间允许100个并发
  12. }
  13. }
  14. }

配置完毕后就可以使用 apache 的 ab 来测试

  1. # 请求 10 次,每次的并发是 1
  2. [root@VM_0_17_centos wwwlogs]# ab -c 2 -n 10 http://www.mytcl.com/

查看访问日志如下

  1. 127.0.0.1 - - [16/Oct/2018:17:45:35 +0800] "GET / HTTP/1.0" 200 6 "-" "ApacheBench/2.3"
  2. 127.0.0.1 - - [16/Oct/2018:17:45:35 +0800] "GET / HTTP/1.0" 200 6 "-" "ApacheBench/2.3"
  3. 127.0.0.1 - - [16/Oct/2018:17:45:35 +0800] "GET / HTTP/1.0" 200 6 "-" "ApacheBench/2.3"
  4. 127.0.0.1 - - [16/Oct/2018:17:45:35 +0800] "GET / HTTP/1.0" 200 6 "-" "ApacheBench/2.3"
  5. 127.0.0.1 - - [16/Oct/2018:17:45:35 +0800] "GET / HTTP/1.0" 200 6 "-" "ApacheBench/2.3"
  6. 127.0.0.1 - - [16/Oct/2018:17:45:35 +0800] "GET / HTTP/1.0" 200 6 "-" "ApacheBench/2.3"
  7. 127.0.0.1 - - [16/Oct/2018:17:45:35 +0800] "GET / HTTP/1.0" 200 6 "-" "ApacheBench/2.3"
  8. 127.0.0.1 - - [16/Oct/2018:17:45:35 +0800] "GET / HTTP/1.0" 200 6 "-" "ApacheBench/2.3"
  9. 127.0.0.1 - - [16/Oct/2018:17:45:35 +0800] "GET / HTTP/1.0" 200 6 "-" "ApacheBench/2.3"
  10. 127.0.0.1 - - [16/Oct/2018:17:45:35 +0800] "GET / HTTP/1.0" 200 6 "-" "ApacheBench/2.3"

参考连接

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注