1、Nginx基本安全優化
a、更改配置文件參數隱藏版本
編輯nginx.conf配置文件增加參數,實現隱藏Nginx版本號的方式如下。在nginx配置文件nginx.conf中的http標簽段內加入 “server_tokens off;”參數,如下:
http{
……
server_tokens off;
……
}
此參數放置在http標簽內,作用是控制http response header內的web服務版本信息的顯示,以及錯誤信息中web服務版本信息的顯示。
server_tokens參數的官方說明如下:
syntax: server_tokens on | off ; #此行為參數語法,on為開啟狀態,off為關閉狀態 default: server_tokens on; #此行意思是不配置該參數,軟件默認情況的結果 context: http,server, location #此行為server_tokens參數可以放置的位置
參數作用:激活或禁止nginx的版本信息顯示在報錯信息和servser的響應首部位置中
Enables or disables emitting of nginx version in error messages and in the "server" response header field
官方資料地址:http://nginx.org/en/docs/http/ngx_http_core_moudule.html
b、更改源碼隱藏nginx軟件名及版本號
第一里程碑:依次修改3個nginx源碼文件
修改第一個文件為nginx-1.10.2/src/core/nginx.h,如下:
[root@web nginx-1.10.2]# sed -n '13,27p' src/core/nginx.h
#define NGINX_VERSION "1.10.2" #修改為想要顯示的版本號,如1.6.2
#define NGINX_VER "nginx/" NGINX_VERSION #將nginx修改為想要修改的軟件名稱,如Apache
#ifdef NGX_BUILD
#define NGINX_VER_BUILD NGINX_VER " (" NGX_BUILD ")"
#else
#define NGINX_VER_BUILD NGINX_VER
#endif
#define NGINX_VAR "NGINX" #將nginx修改為想要修改的軟件名稱,如Apache
#define NGX_OLDPID_EXT ".oldbin"
#endif /* _NGINX_H_INCLUDED_ */
修改第二個文件是nginx-1.10.2/src/http/ngx_http_header_filter_module.c 的49行,需要修改的字符串如下:
[root@web nginx-1.10.2]# grep -n 'Server: nginx' src/http/ngx_http_header_filter_module.c 49:static char ngx_http_server_string[] = "Server: nginx" CRLF; #把“Server: nginx”替換為“Server: Apache”
提示:sed替換命令
sed "49 s#Server: nginx#Server: Apache#" src/http/ngx_http_header_filter_module.c
sed -i "49 s#nginx#Apache#" src/http/ngx_http_header_filter_module.c
修改第三個文件是 nginx-1.10.2/src/http/ngx_http_special_response.c,對外頁面報錯時,它會控制是否展示敏感信息。
[root@web nginx-1.10.2]# sed -n '21,30p' src/http/ngx_http_special_response.c static u_char ngx_http_error_full_tail[] = "<hr><center>" NGINX_VER "</center>" CRLF #此行需要修改,修改為"<hr><center>" NGINX_VER "(http://www.xxx.com)</center>" CRLF
"</body>" CRLF "</html>" CRLF ;
static u_char ngx_http_error_tail[] = "<hr><center>nginx</center>" CRLF #此行需要修改,將對外展示的nginx改為Apache
"</body>" CRLF
注:修改后編譯安裝軟件,啟動服務使其生效。
C、更改nginx服務的默認用戶
為了讓web服務更安全,要盡可能地改掉軟件默認的所有配置,包括端口、用戶等,通用其他軟件服務。
nginx服務啟動后,默認用戶是nobody(編譯安裝時可以指定創建用戶),查看默認配置文件,如下:
[root@web nginx-1.10.2]# grep "#user" conf/nginx.conf.default #user nobody;
為了防止黑客使用默認用戶進行攻擊,用戶需要更改成特殊的用戶,例如www或nginx等等,但用戶必須存在,下面以www用戶為例進行說明。
第一里程碑:創建用戶
useradd -s /sbin/nologin -m www #無需有登錄權限,只需在系統內容執行任務
id www #檢查創建的用戶
第二里程碑:配置nginx服務,讓其使用創建的用戶www用戶(編譯安裝時已指定用戶,無需做此操作)
將默認的#user nobody;改為以下內容: user www www
注:如果注釋或不設置上述參數,默認用戶為nobody用戶,不推薦使用nobody用戶名。
編譯安裝nginx軟件時指定編譯的用戶和組,編譯命令如:
./configure --prefix=/usr/local/nginx-1.10.2 --user=www --group=www --with-http_stub_status_module --with-http_ssl_module
第三里程碑:檢查更改用戶的效果
重新加載配置后,檢查nginx服務進行的對應用戶,如下:
[root@web nginx-1.10.2]# ps -ef | grep nginx | grep -v grep
2、根據nginx.conf配置文件參數優化nginx服務性能
在高並發、高訪問量的web服務場景,需要事先啟動好更多的nginx進程,以保證快速響應並處理大量並發用戶的請求。
a、優化nginx服務的worker進程個數
01、優化nginx進程對應nginx服務的配置參數如下:
#配置文件信息 [root@web nginx-1.10.2]# cat conf/nginx.conf worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; …… } #需要修改的參數: worker_processes 1; #指定了nginx要開啟的進程數,結尾的數字就是進程的個數
注:worker_processes參數調整的是nginx服務的worker進程數,nginx有master進程和worker進程之分,Master為管理員進程,真正接待“顧客”的是worker進程。
02、優化nginx進程個數的策略
work_processes參數大小的設置最好和網站的用戶數量相關聯。
搭建服務器時,worker進程數最開始的設置可以等於CPU的核數,且worker進程數要多一些,這樣起始提供服務時就不會出現因為訪問量快速增加而臨時啟動新進程提供服務的問題,縮短了系統的瞬時開銷和提供服務的時間,提升了服務用戶的速度。高流量高並發場合也可以考慮將進程數提高至CPU核數*2,具體情況要根據實際的業務來選擇,因為這個參數除了要和CPU核數匹配外,也和硬盤存儲的數據及系統的負載有關,設置為CPU的核數是一個好的起始配置。
03、查看web服務器CPU硬件資源信息
下面介紹查看linux服務器CPU總核數的方法。
通過/proc/cpuinfo可查看CPU個數及總核數。查看CPU總核數的示例如下:
[root@web ~]# grep processor /proc/cpuinfo |wc -l 8 #表示為1顆CPU八核
[root@web ~]# grep processor /proc/cpuinfo
查看CPU總顆數的示例如下:
[root@web ~]# grep 'physical id' /proc/cpuinfo |sort|uniq |wc -l 1 #對physical id去重計數,表示1顆CPU
通過執行top命令,然后按數字1,即可顯示所有CPU核數,如下:
[root@web ~]# top #按1顯示多核CPU
top - 09:20:02 up 7:04, 1 user, load average: 0.00, 0.00, 0.00 Tasks: 82 total, 1 running, 81 sleeping, 0 stopped, 0 zombie Cpu0 : 0.3%us, 1.0%sy, 0.0%ni, 98.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Cpu1 : 0.1%us, 1.0%sy, 0.0%ni, 98.2%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Cpu2 : 0.3%us, 1.0%sy, 0.0%ni, 98.3%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Cpu3 : 0.2%us, 1.0%sy, 0.0%ni, 98.8%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Cpu4 : 0.1%us, 1.0%sy, 0.0%ni, 98.4%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Cpu5 : 0.1%us, 1.0%sy, 0.0%ni, 98.2%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Cpu6 : 0.3%us, 1.0%sy, 0.0%ni, 98.1%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Cpu7 : 0.2%us, 1.0%sy, 0.0%ni, 98.9%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Mem: 2493928k total, 485836k used, 2008092k free, 79828k buffers Swap: 1048572k total, 0k used, 1048572k free, 187784k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 7 root 20 0 0 0 0 S 0.3 0.0 0:26.20 events/0 1 root 20 0 19356 1528 1228 S 0.0 0.3 0:02.06 init
注:這是單CPU 八核的信息
例如:CPU核數為8,就配置worker_processes 8
04、實操==》修改nginx配置
第一里程碑:檢查nginx.conf配置文件里的worker_processes數來了解,命令如下:
[root@web conf]# grep worker_processes nginx.conf worker_processes 1;
第二里程碑:修改配置文件中參數
[root@web conf]# sed -i 's#worker_processes 1#worker_processes 8#g' nginx.conf
[root@web conf]# grep worker_processes nginx.conf worker_processes 8;
第三里程碑:平滑啟動nginx,使修改生效,如下:
[root@web conf]# /usr/local/nginx/sbin/nginx -t #檢查配置文件是否有錯,養成修改配置文件后檢查的好習慣(修改配置文件需要先備份) nginx: the configuration file /usr/local/nginx-1.10.2//conf/nginx.conf syntax is ok nginx: configuration file /usr/local/nginx-1.10.2//conf/nginx.conf test is successful [root@web02 conf]# /application/nginx/sbin/nginx -s reload #平滑重啟
第四里程碑:檢查修改后worker進程數量,命令如下:
[root@web conf]# ps -ef | grep nginx | grep -v grep
參考鏈接:http://nginx.org/en/docs/ngx_core_module.html
b、優化綁定不同的nginx進程到不同的CPU上
優化不同的nginx進程對應不同的CPU配置時,八核CPU服務器的參數配置參考如下:
[root@web02 conf]# cat nginx.conf worker_processes 8; worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000 #此行為cpu親和力參數,cpumask為cpu掩碼 events { worker_connections 1024; } ……
worker_cpu_affinity的作用是綁定不同的worker進程數到一組CPU上。通過設置bitmask控制進行允許使用的CPU,默認worker進程不會綁定到任何CPU。
示例配置:
worker_processes 4; worker_cpu_affinity 0001 0010 0100 1000 #綁定每個工作進程到一個單獨的CPU,而
worker_processes 2; worker_cpu_affinity 0101 1010; #綁定第一個工作進程到CPU0/CPU2,第二個工作進程綁定到CPU1/CPU3。第二個例子適用於超線程。 #特殊值auto允許將工作進程自動綁定到可用的CPU: # worker_processes auto; # worker_cpu_affinity auto; 參考鏈接:http://nginx.org/en/docs/ngx_core_module.html#worker_cpu_affinity
C、nginx事件處理模型優化
nginx的聯機處理機制在不同的操作系統會采用不同的I/O模型,在linux下,nginx使用epoll的I/O多路復用模型,在freebsd中使用kequeue的I/O多路復用模型,在Solaris中使用/dev/poll方式的I/O多路復用模型,在windows中使用的是icop等等。
要根據系統類型選擇不同的時間處理模型,可供使用的選擇有“use[kqueue|rtsig|epoll|/dev/poll|select|poll];”,其中select和poll都是標准的工作模式,kqueue和epoll是高效的工作模式,不同的是epoll用在linux平台上,而kqueue用在BSD系統中。對於linux系統linux 2.6.x的內核,推薦選擇epoll工作模式,這是高性能高並發的設置。
本環境使用centos 6.9,因此將nginx的事件模型調整為epoll模型。
具體配置參數如下:
events #events指令是設定nginx的工作模式及連接數上限
{
use epoll;
#use是一個事件模塊指令,用來指定nginx的工作模式。
}
d、調整nginx單個進程允許的客戶端最大連接數
控制連接數的參數為worker_connections,此值要根據具體服務器性能和程序的內存使用量來指定,配置如下:
events #events指令是設定nginx的工作模式及連接數上限 { worker_connections 2048; #最大客戶端連接數由worker_processes和worker_connections決定,即Max_client=worker_processes*worker_connections。進程的最大連接數受linux系統進程的最大打開文件數限制,在執行操作系統命令 “ulimit -Hsh 65535”或配置相應文件后,worker_connections的設置才能生效 }
參考鏈接:http://nginx.org/en/docs/ngx_core_module.html
e、配置nginx worker進程最大打開文件數
參數配置如下:
worker_rlimit_nofile 65535;
#最大打開文件數限制,執行操作系統命令 “ulimit -HSh ”的結果
f、優化服務器域名的散列表大小
在HTTP配置塊中調整server_names_hash_max_size和server_names_hash_bucket_size的值。
server_names_hash_bucket_size的默認值可能是32或64,也可能是其他值,這取決於CPU的緩存行的長度。
g、開啟高效文件傳輸模式
1、設置參數:sendfile on; 2、設置參數:tcp_nopush on; 參考鏈接:http://nginx.org/en/docs/http/ngx_core_module.html#sendfile http://nginx.org/en/docs/http/ngx_core_module.html
h、優化nginx連接參數,調整連接超時時間
nginx連接超時的參數設置: 1、設置參數:keepalive_timeout 60; 2、設置參數tcp_nodelay on; 3、設置參數:client_header_timeout 15; #用於設置讀取客戶端請求頭數據的超時時間。此處的數值為15,其單位是秒,為經驗參考值。 4、設置參數:client_body_timeout 15 #用於設置讀取客戶端請求主題的超時時間,默認值時60. 5、設置參數:send_timeout 25; #用於指定響應客戶端的超時時間。這個超時僅限於兩個連接活動之間的時間,如果超過這個時間,客戶端沒有任何活動,nginx將會關閉連接。
i、上傳文件大小的限制(動態應用)
在主配置文件里加入如下參數:
client_max_body_size 8m; #具體大小根據業務做調整
j、FastCGI相關參數調優(配合PHP引擎動態服務)
FastCGI Cache資料鏈接:http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_cache
worker_processes 4; pid conf/nginx.pid; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log logs/access.log main; sendfile on; tcp_nopush on; keepalive_timeout 65; client_header_timeout 15; client_body_timeout 15; send_timeout 15; gzip on; server_tokens off; fastcgi_connect_timeout 240; fastcgi_send_timeout 240; fastcgi_read_timeout 240; fastcgi_buffer_size 64k; fastcgi_buffer 4 64k; fastcgi_temp_file_write_size 128k; fastcgi_temp_path /data/ngx_fcgi_tmp; fastcgi_cache_path /data/ngx_fcgi_cache levels=2:2 keys_zone=ngx_fcgi_cache:512m inactive=1d max_size=40g; server { listen 80; server_name localhost; access_log logs/host.access.log main; location / { root html; index index.php index.html index.htm; } } location ~ \.php$ { root html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi_conf; fastcgi_cache ngx_fcgi_cache; fastcgi_cache_valid 200 302 1h; fastcgi_cache_valid 301 1d; fastcgi_cache_valid any 1m; fastcgi_cache_min_uses 1; fastcgi_cache_use_stale error timeout invalid_header http_500; fastcgi_cache_key http://$host$request_uri; } ……
k、配置nginx gzip壓縮實現性能優化
目的:節省帶寬、提高訪問速度。
參數介紹及配置:
gzip on #開啟壓縮功能 gzip_min_length 1k; #設置允許壓縮的頁面最小字節數,頁面字節數從header頭的Content-Length中獲取。默認值是0,表示不管頁面多大都進行壓縮,建議設置成大於1k. gzip_buggers 4 16k; #壓縮緩沖區大小。表示申請4個單位為16k的內存作為壓縮結果流緩存,默認值是申請與原始數據大小相同的內存空間來存儲gzip壓縮結果。 gzip_http_version 1.1; #壓縮版本(默認1.1,前端為squid2.5時使用1.0),用於設置識別HTTP協議版本,使用默認即可。 gzip_comp_level 2; #壓縮比率。用來指定gzip壓縮比,1壓縮比最小,處理速度最快;9壓縮比最大,傳輸速度快,單處理最慢,也比較消耗CPU資源。 gzip_types text/plain application/x-javascript text/css application/xml; #用來指定壓縮的類型,“text/html”類型總是會被壓縮,這個就是HTTP原理部分將的媒體類型。 gzip_vary on; #vary header支持。該選項可以讓前端的緩存服務器緩存經過gzip壓縮的頁面。例如用squid緩存經過nginx壓縮的數據。 #完整配置如下: gzip on; gzip_min_length 1k; gzip_buffers 4 32k; gzip_http_version 1.1; gzip_comp_level 9; gzip_types text/css text/xml /app/javascripts; gzip-vary on; 注:不同版本的nginx,gzip_types的配置可能會有不同。
L、配置nginx expires 緩存實現性能優化
目的:降低網站的帶寬、節約成本、加快訪問速度、減輕服務器壓力。
a、根據擴展名進行判斷
nginx expires配置詳解(配置在nginx.conf中的server模塊中): …… server{ …… location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 365d; 當用戶訪問網站URL結尾的文件擴展名為上述指定類型的圖片時,設置緩存365天。 } location ~ .*\.(js | css)?$ { expires 30d; #當用戶訪問網站URL結尾的文件擴展名為js、css類型的元素時,設置緩存30天。 } ……
b、根據URI中的路徑(目錄)進行判斷,添加expires功能范例
location ~ ^/ (images|javascript|js|css|flash|media|static)/ { expires 360d; }
c、單個文件添加expires功能范例
location ~(robots.txt){ expires 7d; #給robots.txt機器人文件設置過去時間,在設置的期間內不記錄404錯誤日志。
break; }
Nginx expires功能缺點及解決方法
當網站被緩存的界面或數據更新了,此時用戶端看到還是舊的已經緩存的內容,這樣就會影響到用戶體驗,解決方法如下:
- 對於經常需要變動的圖片等文件,可以縮短對象緩存時間。例:谷歌的首頁圖片經常根據不同的日期換成一些節日圖,所以可以將這個圖片設置為緩存期1天。
- 當網站改版或更新時,可以在服務器將緩存的對象改名(網站代碼程序)
- 對於網站的圖片、附件,一般不會被用戶直接修改,用戶層面上的修改圖片,實際上個是重新傳到服務器,雖然內容一樣,但是會產生一個新的圖片名稱。
- 網站改版升級會修改js、css等樣式文件,若改版時對這些樣式文件中的元素改了名,會使得前端的CDN及用戶端需要重新緩存內容。
企業網站緩存日期曾經的案例參考:
若企業的業務和網站訪問量不同,那么網站的緩存時間設置也是不同,如下企業所用的緩存日期:
- 51CTO:1周
- 新浪:15天
- 京東:25年
- 淘寶:10年