Web架構之Nginx全方位優化

[TOC]javascript

一、Nginx 安全優化

1.一、隱藏Nginx版本號

通常來講,軟件的漏洞都和版本有關,這個很像汽車的缺陷,同一批次的要有問題就都有問題,別的批次可能就都是好的,Ngnx基於server_tokens關鍵字實現隱藏nginx版本號。php

官方資料css

server_tokens語法:html

syntax:     server_tokens on|off;    #此行爲參數語法,on爲開啓狀態,off爲關閉狀態
default:    server_tokens on;        #此行意思是不配置該參數,軟件默認狀況的結果
context:    http,server,location     #此行爲server_tokens參數能夠放置的位置參數做用:激活或禁止Nginx的版本信息顯示在報錯信息和Server的響應首部位置中。

默認狀況下,訪問nginx會顯示其版本號前端

$ curl -I 127.0.0.1
HTTP/1.1 200 OK
Server: nginx/1.16.1  # 這裏清晰的暴露了Web版本號(1.6.1)及軟件名稱(nginx)
Date: Sat, 14 Mar 2020 06:43:31 GMT
Content-Type: application/octet-stream
Content-Length: 20
Connection: keep-alive

隱藏版本號實現:java

Nginx主配置文件nginx.conf中的http標籤段內加入"server_tokens off"node

http
{
...............
server_tokens off;
...............
}
# 此參數放置在http標籤內,做用是控制http response header內的Web服務版本信息的限制,以及錯誤信息中Web服務版本信息的顯示

修改後重啓nginx,使用curl -I查看結果mysql

$ curl -I 127.0.0.1
HTTP/1.1 200 OK
Server: nginx  # 能夠看到nginx版本號已經被隱藏了
Date: Sat, 14 Mar 2020 06:45:15 GMT
Content-Type: application/octet-stream
Content-Length: 20
Connection: keep-alive

1.二、Nginx更改默認用戶

爲了讓Web服務更安全,要儘量地改掉軟件默認的全部配置,包括端口,用戶等。nginx

那麼如今基於yum安裝的nginx默認用戶都爲nginxweb

1.查看nginx進程

$ ps -ef | grep nginx | grep -v grep
root       2126      1  0 14:05 ?        00:00:00 nginx: master process nginx
nginx      3574   2126  0 14:45 ?        00:00:00 nginx: worker process

能夠看到nginx worker進程是由nginx用戶運行,固然,Nginx的主進程仍是以root身份運行的。

2.查看nginx用戶(默認已建立)

$ id nginx
uid=998(nginx) gid=996(nginx) groups=996(nginx)

3.nginx配置中指定用戶啓動

$ vim /etc/nginx/nginx.conf
user  nginx;   # 指定用戶啓動nginx

二、優化Nginx服務性能

2.一、Nginx指定進程數

在高併發,高訪問量的Web服務場景,須要事先啓動好更多的Nginx進程,以保證快速響應並處理大量併發用戶的請求。 Nginx服務就至關於飯店,網站用戶就至關於顧客,Nginx的進程就至關於服務員,下面就來優化Nginx進程的個數。

worker_processes語法:

syntax:         worker_processes number;    #此行爲參數語法,number爲數量
default:        worker_processes 1;     #此行意思是不匹配該參數,軟件默認狀況數量爲1
context:        main;   #此行爲worker_processes參數能夠放置的位置

上述參數調整的是Nginx服務的worker進程數,Nginx有Master進程和worker進程之分,Master爲管理進程,真正接待「顧客」的是worker進程。

優化Nginx進程個數的策略: worker進程數最開始的設置能夠等於CPU的核數,且worker進程數要多一些,這樣起始提供服務時就不會出現由於訪問量快速增長而臨時啓動新進程提供服務的問題,縮短了系統的瞬時開銷和提供服務的時間,提高了服務用戶的速度。高流量高併發場合也能夠考慮將進程數提升至CPU核數*2,具體狀況要根據實際的業務來選擇,由於這個參數除了要和CPU核數匹配外,也和硬盤存儲的數據及系統的負載有關,設置爲CPU的核數是一個好的起始配置,這也是官方的建議。

實踐修改Nginx配置: 假設服務器的CPU顆數爲2顆,核數爲4核,則初始的配置可經過查看默認的nginx.conf裏的worker_processes數來了解,

$ vim /etc/nginx/nginx.conf
user  nginx;
worker_processes  4; # 這裏修改參數值爲CPU的總核數4,而後從新加載Nginx服務

如今檢查修改後的worker進程數量:

$ ps -ef | grep nginx | grep -v grep
root       2126      1  0 11:02 ?        00:00:00 nginx: master process nginx
nginx      7039   2126  0 15:02 ?        00:00:00 nginx: worker process
nginx      7040   2126  0 15:02 ?        00:00:00 nginx: worker process
nginx      7041   2126  0 15:02 ?        00:00:00 nginx: worker process
nginx      7042   2126  0 15:02 ?        00:00:00 nginx: worker process

2.二、Nginx 進程優化

默認狀況下,Nginx的多個進程有可能跑在某一個CPU或CPU的某一核上,致使Nginx進程使用硬件的資源不均,本節的優化是儘量地分配不一樣的Nginx進程給不一樣的CPU處理,達到充分有效利用硬件的多CPU多核資源的目的。

在優化不一樣的Nginx進程對應不一樣的CPU配置時,四核CPU服務器的參數配置參考以下:

worker_processes 4;
worker_cpu_affinity 0001 0010 0100 1000;
# worker_cpu_affinity就是配置Nginx進程與CPU親和力的參數,即把不一樣的進程分給不一樣的CPU處理。這裏0001 0010 0100 1000是掩碼,分別表明第1,2,3,4核CPU,因爲worker_processes進程數爲4,所以,上述配置會把每一個進程分配一核CPU處理,默認狀況下進程不會綁定任何CPU,參數位置爲main段。

四核和八核CPU服務器的參數配置參考以下:

# 八核掩碼
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
# 四核掩碼
worker_cpu_affinity 0001 0010 0100 1000;
# worker_cpu_affinity 的做用是綁定不一樣的worker進程數到一組CPU上。經過設置bitmask控制進程容許使用的CPU,默認worker進程不會綁定到任何CPU(自動平均分配。)

下面是綁定的實例配置:

worker_processes  4;
worker_cpu_affinity 0001 0010 0100 1000;
worker_processes  2;
worker_cpu_affinity 0101 1010;

# 最佳方式綁定方式 
worker_processes auto;
worker_cpu_affinity auto;

命令方式分配CPU taskset -retrieve or ser a process’s CPU affinity 命令自己也有分配CPU的功能 例如:taskset -c 1,2,3 /etc/init.d/mysqld_start

-c, --cpu-list
              specify  a  numerical  list  of processors instead of a bitmask.  The list may contain multiple items,
              separated by comma, and ranges.  For example, 0,5,7,9-11.

2.三、Nginx 事件模型優化

Nginx的鏈接處理機制在不一樣的操做系統會採用不一樣的額I/O模型,在Linux下,Nginx使用epoll的I/O多路複用模型,在Freebsd中使用kqueue的I/O多路複用模型,在Solaris中使用/dev/poll方式的I/O多路複用模型,在Windows中使用的是icop,等等。要根據系統類型選擇不一樣的事件處理模型,可供使用的選擇有「use [kqueue|rtsig|epoll|/dev/poll|select|poll];」。

事件模型語法:

synstax:  use method;  # 絡模型配置,method選擇模型之一
default:   --  		     # 默認沒有設置
context:  events        # 網絡模型配置放置events區塊內

實踐修改Nginx配置:

$ vi /etc/nginx/nginx.conf
# events 區塊是一個用來設置鏈接進程的區塊,例如:設置Nginx的網絡I/O模型,以及鏈接數等。
events   { 
  use epoll;
}

根據Nginx官方文檔建議,也能夠不指定事件處理模型,Nginx會自動選擇最佳的事件處理模型服務。

2.四、Nginx 最大鏈接數

調整Nginx單個進程容許的客戶端最大鏈接數,這個控制鏈接數的參數爲work_connections,worker_connections的值要根據具體服務器性能和程序的內存使用量來指定(一個進程啓動使用的內存根據程序肯定)

worker_connections語法:

synstax: worker_connections number
default: worker_connections 512
context: events

實踐修改Nginx配置:

$ vi /etc/nginx/nginx.conf
events {
  worker_connections 20480;
}

說明: worker_connections用來設置一個worker process支持的最大併發鏈接數,這個鏈接數包括了全部連接,例如:代理服務器的鏈接,客戶端的鏈接等,實際的併發鏈接數除了受worker_connections參數控制外,還和最大打開文件數worker_rlimit_nofile有關(見下文),Nginx總併發鏈接=worker數量*worker_connections。

參考資料:http://nginx.org/en/docs/ngx_core_module.html

2.五、Nginx 文件描述符

調整配置Nginx worker進程的最大打開文件數,這個控制鏈接數的參數爲worker_rlimit_nofile。

worker_rlimit_nofile語法:

synstax: worker_rlimit_nofile number
default: 無
context: main

實踐修改Nginx配置:

$ vi /etc/nginx/nginx.conf
# 最大打開文件數,可設置爲系統優化後的ulimit-HSn的結果
worker_rlimit_nofile 65535;

說明: 1.此參數的做用是改變worker processes能打開的最大文件數 2.Linux系統文件最大打開數設置:ulimit -n 65535

參考資料:http://nginx.org/en/docs/ngx_core_module.html

2.六、Nginx高效傳輸

1.設置參數:sendfile on; sendfile參數用於開啓文件的高效傳輸模式。同時將tcp_nopush和tcp_nodelay兩個指令設置爲on,可防止網絡及磁盤I/O阻塞,提高Nginx工做效率。

syntax:     sendfile on | off;  
default:    sendfile off;     
context:    http,server,location,if in location

參數做用:激活或禁用sendfile()功能功能。sendfile()是做用於兩個文件描述符之間的數據拷貝函數,這個拷貝操做是在內核之中的,被稱爲「零拷貝」,sendfile()比read和write函數要高效不少,由於,read和write函數要把數據拷貝到應用層再進行操做。相關控制參數還有sendfile_max_chunk。

細節見http://nginx.org/en/docs/http/ngx_http_core_module.html#sendfile

2.設置參數:tcp_nopush on; 提升網絡的「傳輸效率」

syntax:     tcp_nopush on | off;   
default:    tcp_nopush off;     
context:    http,server,location

參數做用:激活或禁用Linux上的TCP_CORK socket選項,此選項僅僅當開啓sendfile時才生效,激活這個tcp_nopush參數,數據包不會立刻轉發出去,而是等數據包最大時,一次性轉發出去,有效解決網絡堵塞。

細節見http://nginx.org/en/docs/http/ngx_http_core_module.html。

3.設置參數:tcp_nodelay on; 在keeplive鏈接下,提升網絡的傳輸「實時性」 用於激活tcp_ondelay功能,提升I/O性能。

syntax:     tcp_nodelay on | off   
default:    tcp_nodelay on;        
context:    http,server,location

參數做用:默認狀況下當數據發送時,內核並不會立刻發送,可能會等待更多的字節組成一個數據包,這樣能夠提升I/O性能。可是,在每次只發送不多字節的業務場景中,使用 tcp_nodelay功能可以讓數據包馬上轉發出去。

參數生效條件: 激活或禁用TCP_NODELAY選項,當一個鏈接進入keep-alive狀態時生效。 細節見http://nginx.org/en/docs/http/ngx_http_core_module.html。

三、Nginx鏈接參數優化

1.keepalive_timeout 用於設置客戶端鏈接保持會話的超時時間爲60秒。超過這個時間,服務器會關閉該鏈接,此數值爲參考值。

syntax: keepalive_timeout  timeout [header_timeout] 
default: keepalive_timeout 75s;  
context: http,serverr,location

參數做用:keep-alive可使客戶端到服務器端已經創建的鏈接一直工做不退出,當服務器有持續請求時,keep-alive會使用已經創建的鏈接提供服務,從而避免服務器從新創建新鏈接處理請求。

此參數設置一個keep-alive(客戶端鏈接在服務器端保持多久後退出),其單位是秒,和HTTP響應header域的「Keep-Alive:timeout=time」參數有關,這些header信息也會被客戶端瀏覽器識別並處理,不過有些客戶端並不能按照服務器端的設置來處理,例如:MSIE大約60秒後會關閉keep-alive鏈接。 細節見:http://nginx.org/en/docs/http/ngx_http_core_module.html

2.client_header_timeout 用於設置讀取客戶端請求頭數據的超時時間。此處的數值15,其單位是秒,爲經驗參考值。

syntax:     client_header_timeout time; #<==參數語法
default:    client_header_timeout 60s;  #<==參數默認大小
context:    http,server         #<==能夠放置的標籤段

參數做用:設置讀取客戶端請求頭數據的超時時間。若是超過這個時間,客戶端尚未發送完整的header數據,服務器端將返回「Request time out (408)」錯誤,可指定一個超時時間,防止客戶端利用http協議進行攻擊。

細節見:http://nginx.org/en/docs/http/ngx_http_core_module.html。

3.client_body_timeout 用於設置讀取客戶端請求主體的超時時間,默認值60

syntax:     client_body_timeout time;  
default:    client_body_timeout 60s;  
context:    http,server,location

參數做用:設置讀取客戶端請求主體的超時時間。這個超時僅僅爲兩次成功的讀取操做之間的一個超時,非請求整個主體數據的超時時間,若是在這個超時時間內,客戶端沒有發送任何數據,Nginx將返回「Request time out(408)」錯誤,默認值60,

細節見:http://nginx.org/en/docs/http/ngx_http_core_module.html

4.send_timeout 25 用於指定響應客戶端的超時時間。這個超時僅限於兩個鏈接活動之間的時間,若是超過這個時間,客戶端沒有任何活動或者Nginx數據沒有發送完,Nginx都將會關閉鏈接,默認值爲60秒,能夠改成參考值25秒。

syntax:     send_timeout    time; 
default:    send_timeout    60s;    
context:    http,server,location

參數做用:設置服務器端發送HTTP響應信息到客戶端的超時時間,這個超時僅僅爲兩次成功握手後的一個超時,非請求整個響應數據的超時時間,如在這個超時時間內,客戶端沒有接收任何數據,鏈接將被關閉。

細節見http://nginx.org/en/docs/http/ngx_http_module.html。

四、Nginx上傳文件大小限制

syntax:     client_max_body_size size;  
default:    client_max_body_size 1m;   
context:   http,server,location

參數做用:設置最大的容許的客戶端請求主體大小,在請求頭域有「Content-Length」,若是超過了此配置值,客戶端會受到413錯誤,意思是請求的條目過大,有可能瀏覽器不能正確顯示。設置爲0表示禁止檢查客戶端請求主體大小。此參數對提升服務器端的安全性有必定做用。細節見http://nginx.org/en/docs/http/ngx_http_core_module.html

具體大小根據公司的業務作調整,若是不清楚就先設置爲8m把,有關客戶端請求主體的解釋在HTTP原理一節已經解釋過了,通常狀況下,HTTP的post方法在提交數據時纔會攜帶請求主體信息。

五、FastCGI調優

FastCGI參數是配合Nginx向後請求PHP動態引擎服務的相關參數。 FastCGI常見參數的Nginx配置示例以下:

$ cat /etc/nginx/nginx.conf
worker_processes  4;
worker_cpu_affinity 0001 0010 0100 1000;
worker_rlimit_nofile 65535;
user nginx;
events {
    use epoll;
    worker_connections  10240;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    tcp_nopush      on;
    keepalive_timeout  65;
    tcp_nodelay     on;
    client_header_timeout 15;
    client_body_timeout   15;
    send_timeout          15;
    server_tokens off;
    fastcgi_connect_timeout 30s;        #Nginx容許fcgi鏈接超時時間
    fastcgi_send_timeout 30s;           #Nginx容許fcgi返回數據的超時時間
    fastcgi_read_timeout 30s;           #Nginx讀取fcgi響應信息的超時時間
    fastcgi_buffer_size 64k;            #Nginx讀取響應信息的緩衝區大小
    fastcgi_buffers 4 64k;              #指定Nginx緩衝區的數量和大小
    fastcgi_busy_buffers_size 128k;     #當系統繁忙時buffer的大小
    fastcgi_temp_file_write_size 128k;  #Nginx臨時文件的大小
    fastcgi_temp_path   /data/ngx_fcgi_tmp; #指定Nginx臨時文件放置路徑
    fastcgi_cache_path  /data/ngx_fcgi_cache    levels=2:2  keys_zone=ngx_fcgi_cache:10m   inactive=1d;    #指定Nginx緩存放置路徑
    
    server {
        listen       80;
        location ~ .*\.(php|php5)?$ {
                root   html;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        include fastcgi.conf;
        fastcgi_cache ngx_fcgi_cache;     #開啓fcgi緩存並起名叫ngx_fcgi_cache,很重要,有效下降CPU負載,而且防止502錯誤發生。
        fastcgi_cache_valid 200 302 1h; #指定應答代碼的緩存時間,1h=1小時
        fastcgi_cache_valid 301 1d;     #1d=1天
        fastcgi_cache_valid any 1m;     #and 1m:將其餘應答緩存1分鐘
        fastcgi_cache_min_uses 1;       #待緩存內容至少要被用戶請求過1次
        fastcgi_cache_use_stale error timeout invalid_header http_500;  #當遇到error,timeout,或者返回碼500時,啓用過時緩存返回用戶(返回過時也比返回錯誤強)
#       fastcgi_cache_key   http://$host$request_uri;   
        
        }
    }

六、Nginx gzip

Nginx gzip壓縮模塊提供了壓縮文件內容的功能,用戶請求的內容在發送到用戶客戶端以前,Nginx服務器會根據一些具體的策略實施壓縮,以節約網站出口帶寬,同時加快數據傳輸效率,來提高用戶訪問體驗。

Nginx gzip壓縮的優勢 1.提高網站用戶體驗:發送給用戶的內容小了,用戶訪問單位大小的頁面就加快了,用戶體驗提高了,網站口碑就行了。 2.節約網站帶寬成本:數據是壓縮傳輸的,所以節省了網站的帶寬流量成本,不過壓縮時會稍微消耗一些CPU資源,這個通常能夠忽略。

此功能既能提高用戶體驗,又能使公司少花錢,一舉多得。對於幾乎全部的Web服務來講,這是一個很是重要的功能,Apache服務也有此功能。

須要和不須要壓縮的對象 1.純文本內容壓縮比很高,所以,純文本的內容最好進行壓縮,例如:html,js,css,xml,shtml等格式的文件。 2.被壓縮的純文本文件必需要大於1KB,因爲壓縮算法的特殊緣由,極小的文件壓縮後可能反而變大。 3.圖片,視頻(流媒體)等文件儘可能不要壓縮,由於這些文件大多都是通過壓縮的,若是再壓縮極可能不會減小或減小不多,或者有可能增大,同時壓縮時還會消耗大量的CPU,內存資源。

參數介紹及配置說明 此壓縮功能與早期Apache服務的mod_deflate壓縮功能很類似,Nginx的gzip壓縮功能依賴於ngx_http_gzip_module模塊,默認已安裝。

1.gzip壓縮配置語法

Syntax:	gzip on | off;
Default:	 gzip off;
Context:	http, server, location, if in location
做用:傳輸壓縮

2.gzip壓縮比率配置語法

Syntax:	gzip_comp_level level;
Default:	gzip_comp_level 1;
Context:	http, server, location
做用:壓縮自己比較耗費服務端性能

3.gzip壓縮協議版本

Syntax:	gzip_http_version 1.0 | 1.1;
Default:	gzip_http_version 1.1;
Context:	http, server, location
做用:壓縮使用在http那個協議,主流版本1.1

4.擴展壓縮模塊

Syntax:	gzip_static on | off | always;
Default:	
gzip_static off;
Context:	http, server, location
做用:預讀gzip功能

對應的壓縮參數說明以下:

#壓縮配置
gzip on;
#<==開啓gzip壓縮功能

gzip_min_length 1k;
#<==設置容許壓縮的頁面最小字節數,頁面字節數從header頭的Content-Length中獲取。默認值0,表示無論頁面多大都進行壓縮。建議設置成大於1K,若是小於1K可能會越壓越大。

gzip_buffers 4 16K;
#<==壓縮緩衝區大小。表示申請4個單位爲16K的內存做爲壓縮結果流緩衝,默認值是申請與原始數據大小相同的內存空間來存儲gzip壓縮結果。

gzip_http_version 1.1;
#<==壓縮版本(默認1.1,前端爲squid2.5時使用1.0),用於設置識別HTTP協議版本,默認是1.1,目前大部分瀏覽器已經支持GZIP解壓,使用默認便可。

gzip_comp_level 2;
#<==壓縮比率。用來指定gzip壓縮比,1壓縮比最小,處理速度最快;9壓縮比最大,傳輸速度快,但處理最慢,也比較消耗CPU資源。

gzip_types text/plain text/css application/x-javascript application/xml application/javascript application/javascript  image/jpeg image/jpg image/png;  
#<==用來指定壓縮的類型,「text/html」類型老是會被壓縮,這個就是HTTP原理部分講的媒體類型。壓縮類型能夠在../conf/mime.types文件中查看

gzip_vary on;
#<==vary header支持。該選項可讓前端的緩存服務器緩存通過gzip壓縮的頁面,例如用Squid緩存通過Nginx壓縮的數據。

不一樣的Nginx版本中,gzip_types的配置可能會有不一樣,上述配置示例適合Nginx 1.6.3。對應的文件類型,請查看安裝目錄下的mime.types文件。

完整的配置以下:

gzip on;
gzip_min_length 1k;
gzip_buffers 4 16K;
gzip_http_version 1.1;
gzip_comp_level 9;
gzip_types text/plain text/css application/x-javascript application/xml application/javascript  image/jpeg image/jpg image/png;  
gzip_vary on;

更多:http://nginx.org/en/docs/http/ngx_http_gzip_module.html

七、Nginx Expires 緩存

簡單說,Nginx expires的功能就是爲用戶訪問的網站內容設定一個過時時間,當用戶第一次訪問這些內容時,會把這些內容存儲在用戶瀏覽器本地,這樣用戶第二次及之後繼續訪問該網站時,瀏覽器會檢查加載已經緩存在用戶瀏覽器本地的內容,就不會去服務器請求了,當緩存的內容過時了會向源服務器發送請求,檢查緩存內容是否被修改。

更深刻的理解: expires的功能就是容許經過Nginx配置文件控制HTTP的「Expires」和「Cache-Control」響應頭部內容,告訴客戶端瀏覽器是否緩存和緩存多久之內訪問的內容。這個expires模塊控制Nginx服務器應答時的expires頭內容和Cache-Control頭的max-age指令。緩存的有效期能夠設置爲相對於源文件的最後修改時刻或客戶端的訪問時刻。 這些HTTP頭向客戶端代表了額內容的有效性和持久性。若是客戶端本地有內容緩存,則內容就能夠從緩存而不是從服務器中讀取,而後客戶端會檢查緩存中的副本,看其是否過時或失效,以決定是否從新從服務器得到內容更新。

Nginx expires功能優勢 1.expires能夠下降網站的帶寬,節約成本。 2.加快用戶訪問網站的速度,提高用戶訪問體驗。 3.服務器訪問量下降了,服務器壓力就減輕了,服務器成本也會下降,甚至能夠節約人力成本。 4.對於幾乎全部的Web服務來講,這是很是重要的功能之一,Apache服務也有此功能。

Nginx expires配置詳解 前面已經介紹了expires的功能原理,接下來就來配置Nginx expires的功能。這裏以location標籤爲例進行講解,經過location URI規則將須要緩存的擴展名列出來,而後指定緩存時間。若是針對全部內容設置緩存,也能夠不用location。Nginx默認安裝了expires功能。

1.根據文件擴展名進行判斷,添加expires功能範例 範例1:

location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
    expires 3650d;
}
#該範例的意思是當用戶訪問網站URL結尾的文件擴展名爲上述指定類型的圖片時,設置緩存3650天,即10年。

範例2:

location ~ .*\.(js|css)$
 {
    expires 30d;
 }
#該範例的意思是當用戶訪問網站URL結尾的文件擴展名爲js,css類型的元素時,設置緩存30天,即1個月。

2.根據URL中的路徑(目錄)進行判斷,添加expires功能範例 範例3:

location ~ ^/(images|javascript|js|css|flash|media|static)/
{
    expires 360d;
}
#該範例的意思是當用過戶訪問網站URL中包含上述路徑(例:images,js,css,這些在服務器端是程序目錄)時,把訪問的內容設置緩存360天,即1年。

3.配置Nginx expire配置效果檢查

$ cat nginx.conf                          
worker_processes  1;
events {
    worker_connections  1024;
}
worker_rlimit_nofile 65535;
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    server_tokens off;
    tcp_nopush on;
    tcp_nodelay on;
    gzip on;
    gzip_min_length 1k;
    gzip_buffers 4 16K;
    gzip_http_version 1.1;
    gzip_comp_level 9;
    gzip_types text/plain application/x-javascript text/css application/xml;
    gzip_vary on;

    server {
        listen       80;
        server_name  blog.youngboy.org;
        root html/blog;
        location / {
            index  index.php index.html index.htm;
        }
        location ~.*\.(php|php5)?$ {
             fastcgi_pass 127.0.0.1:9000;
             fastcgi_index index.php;
             include fastcgi.conf;
                }
        location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
             expires 3650d;
                }

        location ~ .*\.(js|css)$ {
              expires 30d;
                 }

          location ~ ^/(images|javascript|js|css|flash|media|static)/ {
               expires 360d;
                }
        }
}

使用curl -I 查看expires參數

[root@web01 /]# curl -I http://www.xiongminghao.top/wp-content/themes/wordstar/assets/css/font-awesome.css
HTTP/1.1 200 OK
Server: nginx
Date: Sat, 05 Jan 2019 16:43:02 GMT
Content-Type: text/css
Content-Length: 37414
Last-Modified: Sat, 29 Dec 2018 07:13:51 GMT
Connection: keep-alive
Vary: Accept-Encoding
ETag: "5c271eaf-9226"
Expires: Mon, 04 Feb 2019 16:43:02 GMT #緩存過時時間
Cache-Control: max-age=2592000 #緩存的總時間
Accept-Ranges: bytes

注意事項:expires只能在web節點上的nginx的配置文件裏生效,若是配置在nginx方向代理的話,expires是不生效的

八、Nginx 日誌文件安全

1.不記錄特定的訪問日誌 在實際工做中,對於負載均衡器健康節點檢查或某些特定文件(好比圖片,JS,CSS)的日誌,通常不須要記錄下來,由於在統計PV時是按照頁面計算的,並且日誌寫入太頻繁會消耗大量磁盤I/O,下降服務的性能。 具體配置方法爲:

location ~ .*\.(js|jpg|JPG|jpeg|JPEG|css|bmp|gif|GIF)$ {
    access_log  off;
}

這裏用location標籤匹配不記錄日誌的元素擴展名,而後關閉日誌

2.訪問日誌的權限設置 假如日誌目錄爲/app/logs,則受權方法以下:

chown -R root.root /app/logs
chmod -R 600 /app/logs

不須要在日誌目錄上給Nginx用戶讀或寫許可,但不少網友都沒注意這個問題,他們把該權限直接給了Nginx或Apache用戶,這就成爲了安全隱患。

九、Nginx 訪問控制

1.根據擴展名限制程序和文件訪問 Web2.0時代,絕大多數網站都是以用戶爲中心多的,例如:bbs,blog,sns產品,這幾個產品都有一個共同特色,就是不但容許用戶發佈內容到服務器,還容許用戶發圖片甚至上傳附件到服務器上,因爲爲用戶開了上傳功能,所以給服務器帶來了很大的安全風險。雖然不少程序在上傳前會着必定的控制,例如:文件大小,類型等,可是,一不當心就會被黑客鑽了控制,上傳了木馬程序。

下面將利用Nginx配置禁止訪問和上傳資源目錄下的PHP,Shell,Perl,Python程序文件,這樣用戶即便上傳了木馬文件也無法執行,從而增強了網站的安全。

範例1:配置Nginx,禁止解析指定目錄下的指定程序。

location ~ ^/images/.*\.(php|php5|sh|pl|py)$ {
    deny all;
}

location ~ ^/static/.*\.(php|php5|sh|pl|py)$	{
    deny all;
}
location ~* ^/data/(attachment|avatar)/.*\.(php|php5)$ {
    deny all;
}

對上述目錄的限制必須寫在Nginx處理PHP服務配置的前面,以下:

location ~ .*\.(php|php5)$
{
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    include fcgi.conf;
}

範例2:Nginx下配置禁止訪問*.txt和*.doc文件。 實際配置信息以下:

location ~* \.(txt|doc)$
{
    if (-f $request_filename)
    {
        root /data/www/www;
        #rewrite ...能夠重定向到某個URL
        break;
    }
}
location ~* \.(txt|doc)$
{
    root /data/www/www;
    deny all;
}

2.禁止訪問指定的目錄 範例1:配置禁止訪問指定的單個或多個目錄

#禁止訪問單個目錄的命令以下:
location ~ ^/static  {
    deny all;
}

#禁止訪問多個目錄的命令以下:
location ~ ^/(static|js)  {
    deny all;
}

範例2:禁止訪問目錄並返回指定的HTTP狀態碼,命令以下:

server  {
    listen 80;
    server_name www.youngboy.com youngboy.com;
    root /data/www/www;
    index index.html index.htm;
    access_log logs/www_access.log commonlog;
    location /admin/ {return 404;}
    location /tmplates/ {return 403;}
}

做用: 禁止訪問目錄下的指定文件"1",或者禁止訪問指定目錄下的全部內容。

最佳應用場景: 對於集羣的共享存儲,通常是存放靜態資源文件,因此,可禁止執行指定擴展名的程序,例:.php,.sh,.pl,.py

十、Nginx 限制來源IP訪問

使用ngx_http_access_module限制網站來源IP訪問

案例環境:phpmyadmin數據庫的Web客戶端,內部開發人員用的。 範例1:禁止某目錄讓外界訪問,但容許某IP訪問該目錄,且支持PHP解析,命令以下:

location ~ ^/yunjisuan/ {
    allow 202.111.12.211;
    deny all;
}

location ~ .*\.(php|php5)$ {
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index   index.php;
    include         fastcgi.conf;
}

範例2:限制指定IP或IP段訪問,命令以下:

location / {
    deny  192.168.1.1;
    allow 192.168.1.0/24;
    allow 10.1.1.0/16;
    deny  all;
}

參考資料:http://nginx.org/en/docs/http/ngx_http_access_module.html

企業問題案例: Nginx作反向代理的時候能夠限制客戶端IP嗎? 答:能夠,具體方法以下:

#方法一:使用if來控制,命令以下:
if ($remote_addr = 10.0.0.7) {
    return 403;
}

if ($remote_addr = 218.247.17.130) {
    set $allow_access_root 'ture';     
}

#方法二:利用deny和allow只容許IP訪問,命令以下:
location / {
    root html/blog;
    index index.php index.html index.htm;
    allow 10.0.0.7;
    deny all;
}

#方法三:只拒絕某些IP訪問,命令以下:
location / {
    root html/blog;
    index index.php index.html index.htm;
    deny 10.0.0.7;
    allow all;
}

注意事項: 1.deny必定要加一個IP,不然會直接跳轉到403,再也不往下執行了,若是403默認頁是在同一域名下,會形成死循環訪問。 2.對於allow的IP段,從容許訪問的段位從小到大排列,如127.0.0.0/24的下面才能是10.10.0.0/16,其中: 1)24表示子網掩碼:255.255.255.0 2)16表示子網掩碼:255.255.0.0 3)8表示子網掩碼:255.0.0.0 3.以deny all:結尾,表示除了上面容許的,其餘的都禁止。如: 1)deny 192.168.1.1; 2)allow 127.0.0.0/24; 3)allow 192.168.0.0/16; 4)allow 10.10.0.0/16; 5)deny all;

十一、Nginx 禁止非法域名解析

Nginx如何防止用戶IP訪問網站(惡意域名解析,也至關因而直接IP訪問企業網站)

方法一:讓使用IP訪問網站的用戶,或者惡意解析域名的用過戶,收到501錯誤,命令以下:

#直接用新的server標籤
server {
    listen 80 default_server;
    server_name _;
    return 501;
}
說明:直接報501錯誤,從用戶體驗上不是很好

方法二:經過301跳轉到主頁,命令以下:

#當輸入IP地址訪問的時候會自動跳轉到域名
server {
    listen 80 default_server;
    server_name _;
    rewrite ^(.*) http://blog.youngboy.org/$1 permanent;
}

方法三:發現某域名惡意解析到公司的服務器IP,在server標籤裏添加如下代碼便可,如有多個server則要多處添加。

if ($host !~ ^blog.youngboy.org$) {
        rewrite ^(.*) http://blog.youngboy.org/$1 permanent;
                }
#說明:代碼含義爲若是header信息的host主機名字非blog.youngboy.org,就301跳轉到blog.youngboy.org

十二、Nginx 防盜鏈

簡單的說,就是某些不法網站未經容許,經過在其自身網站程序裏非法調用其餘網站的資源,而後在本身的網站上顯示這些調用的資源,達到填充自身網站的效果。這一舉動不只浪費了調用資源網站的網絡流量,還形成其餘網站的帶寬及服務壓力吃緊,甚至宕機。

Nginx Web服務實現防盜鏈實戰 在默認狀況下,只須要進行簡單的配置,便可實現防盜鏈處理。請看下面的實例。

實戰模式演示盜鏈: 1)假定blog.youngboy.com是盜鏈的網站域名,先寫一個代碼程序內容,以下:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
<title>
jason
</title>
</head>
<body bgcolor=green>
<img src="http://www.youngboy.org/stu.jpg">
</body>
</html>

假定咱們維護的網站是www.youngboy.org。設定一張存在的圖片地址,www. youngboy.org/stu.jpg,此時發現blog.youngboy.com盜鏈了。經過查看流量,分析日誌看referer,就能夠看到被盜鏈的具體狀況。

下面是查看Web用戶http_referer實戰演示

#nginx日誌格式爲www.access.log
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

盜鏈網站blog.youngboy.com訪問咱們的站點時記錄的日誌

[root@web01 logs]# tail -f www.access.log 
10.0.0.1 - - [16/Oct/2018:08:56:43 +0800] "GET /stu.jpg HTTP/1.1" 304 0 "http://blog.youngboy.com/oldboy.html" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.16 Safari/537.36" "-"

對比下可知,盜鏈的網站多出了一個http_referer的信息,即"http://blog.youngboy.com/oldboy.html" ,表示用戶打開咱們網站的資源來自於此網站,也就是該站盜鏈了咱們的網站www.youngboy.org資源 可在www.youngboy.org網站下設置防盜鏈,Nginx的方法以下 放置在server標籤內

location ~*^.+\.(jpg|gif|png)$ {
    valid_referers none blocked *.youngboy.com youngboy.com;      
		if ($invalid_referer) {
        rewrite ^/ http://www.youngboy.com/img/nolink.jpg;
   			}
}
#提示:要根據本身公司的實際業務(是否有外鏈的合做)進行域名設置。

盜鏈的配置參數解釋

location ~*^.+\.(jpg|gif|png)$ { 
#若是訪問的文件匹配了括號中的結尾的擴展名,那麼就執行下一步匹配
valid_referers none blocked *.youngboy.com youngboy.com;    
#若是http報文中referer不是youngboy.com,那麼就執行一步匹配
  if ($invalid_referer) {
        rewrite ^/ http://www.youngboy.com/img/nolink.jpg;
#若是條件不成立,也就是說在http報文中的referer中的域名不是上述填寫的域名,那麼就會給客戶端返回http://www.youngboy.com/img/nolink.jpg;
    }
}

1三、Nginx 優雅錯誤

範例1:對錯誤代碼403實行本地頁面跳轉,命令以下:

server {
    listen 80;
    server_name     blog.youngboy.org;
    location / {
        root html/blog;
        index   index.html  index.htm;
    }
    error_page  403 /403.html;    #當出現403錯誤時,會跳轉到403.html頁面
}

[root@web01 html]# echo 「jason 403 page」 >blog/403.html 
[root@web01 blog]# curl blog.youngboy.org/images/oldgirl.sh
jason 403 page
#上面的/403.html是相對於站點根目錄html/blog的。

範例2:對錯誤代碼404實行本地頁面優雅顯示,命令以下

server {
    listen  80;
    server_name blog.youngboy.org;
    location / {
        root    html/blog;
        index   index.html  index.htm;
        error_page  404 /404.html; #當出現404錯誤時,會跳轉到404.html頁面
    }
}
#代碼中的/404.html是相對於站點根目錄html/blog下的404.html文件,該文件能夠是.php .jpg .html等等
error_page支持多個錯誤代碼的跳轉例如:
      error_page 403 404 /403.html;

範例3: 50x頁面放到本地單獨目錄下,進行優雅顯示

error_page  500 502 503 504 /50x.html;
location = /50x.html {
    root    /data/www/html;
}     
#這裏指定單獨的站點目錄存放到50x.html文件中。

範例4: 錯誤狀態碼URL重定向,命令以下:

server {
    listen 80;
    server_name blog.youngboy.org;
    location / {
        root    html/www;
        index   index.html  index.htm;
        error_page  404 http://bbs.youngboy.org; #當出現404錯誤時,會跳轉到指定的URL http://bbs.youngboy.org頁面顯示給用戶,這個URL通常是企業另外的可用地址。

        access_log  /usr/local/nginx/logs/bbs_access.log    commonlog;
    }
}
#代碼中的/404.html是相對於站點根目錄html/www的。

範例5: 將錯誤狀態碼重定向到一個location,命令以下:

location / {
    error_page  404 = @fallback;
}
location @fallback {
    proxy_pass  http://backend;
}

阿里門戶網站天貓的Nginx優雅顯示配置案例以下:

error_page  500 501 502 503 504 http://err.tmall.com/error2.html;
error_page  400 403 404 405 408 410 411 412 413 414 415 http://err.tmall.com/error1.html;

1四、Nginx 防爬蟲

咱們能夠根據客戶端的user-agents信息,輕鬆地阻止指定的爬蟲爬取咱們的網站。下面來看幾個案例。 將配置放入server標籤 範例1:阻止下載協議代理,命令以下:

##Block download agents##
if ($http_user_agent ~* LWP:Simple|BBBike|wget) {
    return 403;
}
#若是用戶匹配了if後面的客戶端(例如wget),就返回403.
#這裏根據$http_user_agent獲取客戶端agent,而後判斷是否容許或返回指定錯誤碼。

範例2:添加內容防止N多爬蟲代理訪問網站,命令以下:

#這些爬蟲代理使用「|」分隔,具體要處理的爬蟲能夠根據需求增長或減小,添加的內容以下:
if ($http_user_agent ~* "qihoobot|Baiduspider|Googlebot-Modile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Yahoo! SSlurp  China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot"){
    return 403;
}

範例3:測試禁止不一樣的瀏覽器軟件訪問,命令以下:

if ($http_user_agent ~* "Firefox|MSIE") {
    rewrite ^(.*) http://blog.youngboy.org/$1 permanent;
}
#若是瀏覽器爲Firefox或IE,就會跳轉到http://blog.youngboy.org

1五、Nginx 限制HTTP請求方法

最經常使用的HTTP方法爲GET,POST,咱們能夠經過Nginx限制HTTP請求的方法來達到提高服務器安全的目的,例如,讓HTTP只能使用GET,HEAD和POST方法的配置以下:

#Only allow these request methods
if ($request_method !~ ^(GET|HEAD|POST)$) {
    return 501;
}

#命令解釋:
($request_method !~ ^(GET|HEAD|POST)$)  #<==若是匹配的http請求方法不是get|head|post就拒絕掉

當上傳服務器上傳數據到存儲服務器時,用戶上傳寫入的目錄就不得不給Nginx對應的用戶相關權限,這樣一旦程序有漏洞,木馬就有可能被上傳到服務器掛載的對應存儲服務器的目錄裏,雖然咱們也作了禁止PHP,SH,PL,PY等擴展名的解析限制,但仍是會遺漏一些想不到的可執行文件。對於這樣狀況,該怎麼辦呢?事實上,還能夠經過限制上傳服務器的Web服務(能夠具體到文件)使用GET方法,防止用戶經過上傳服務器訪問存儲內容,讓訪問存儲渠道只能從靜態或圖片服務器入口進入。

例如,在上傳服務器上限制HTTP的GET方法的配置以下:

#Only deny GET request methods ##
if ($request_method ~* ^(GET)$) {
    return 501;
}
#還能夠加一層location,更具體地限制文件名

1六、Nginx 鏈接限制

鏈接頻率限制 limit_conn_module 請求頻率限制 limit_req_module

http協議的鏈接與請求

HTTP是建⽴在TCP, 在完成HTTP請求須要先建⽴TCP三次握⼿(稱爲TCP鏈接),在鏈接的基礎 上在HTTP請求。

Nginx鏈接限制配置

Nginx鏈接限制語法

Syntax: limit_conn_zone key zone=name:size; 
Default: Context: http

Syntax: limit_conn zone number; 
Default: Context: http, server, location

具體配置以下:

http {  #http段配置鏈接限制, 同⼀時刻只容許⼀個客戶端IP鏈接 
limit_conn_zone $binary_remote_addr zone=conn_zone:10m;

...

server {

...

location / {
#同⼀時刻只容許⼀個客戶端IP鏈接 
limit_conn conn_zone 1; 
}

#壓⼒測試 yum install -y httpd-tools ab -n 50 -c 20 http://127.0.0.1/index.html

Nginx 請求限制配置

Nginx請求限制語法 
Syntax: limit_req_zone key zone=name:size rate=rate; Default: Context: http
Syntax: limit_conn zone number [burst=number] [nodelay]; Default: Context: http, server, location

具體配置以下:

http {  ##http段配置請求限制, rate限制速率,限制⼀秒鐘最多⼀個IP請求 
limit_req_zone $binary_remote_addr zone=req_zone:10m rate=1r/s;

...

server {

...

location / { 
#1r/s只接收⼀個請求,其他請求拒絕處理並返回錯誤碼給客戶端

limit_req zone=req_zone; 
#請求超過1r/s,剩下的將被延遲處理,請求數超過burst定義的數量, 多餘的請求返回503

#limit_req zone=req_zone burst=3 nodelay; }

#壓⼒測試 yum install -y httpd-tools ab -n 50 -c 20 http://127.0.0.1/index.html

鏈接限制沒有請求限制有效?

咱們前⾯說過, 多個請求能夠建⽴在⼀次的TCP鏈接之上, 那麼咱們對請求的精度限制,固然

⽐對⼀個鏈接的限制會更加的有效。

由於同⼀時刻只容許⼀個鏈接請求進⼊。 可是同⼀時刻多個請求能夠經過⼀個鏈接進⼊。 因此請求限制纔是⽐較優的解決⽅案。

相關文章
相關標籤/搜索