(1).隱藏nginx版本號
隱藏版本號可以有效避免黑客根據nginx版本信息,查找對應漏洞進行攻擊。
下載nginx源碼包(http://nginx.org/en/download.html)並上傳,在源碼編譯之前修改相應配置文件。
[root@youxi1 ~]# tar zxf nginx-1.16.0.tar.gz -C /usr/local/src/ [root@youxi1 ~]# cd /usr/local/src/nginx-1.16.0/ [root@youxi1 nginx-1.16.0]# vim src/core/nginx.h //修改軟件版本號 #define NGINX_VERSION "7.0.0" //第13行 #define NGINX_VER "IIS/" NGINX_VERSION //第14行 //修改HTTP頭信息中的connection字段,防止回顯具體版本號 [root@youxi1 nginx-1.16.0]# vim src/http/ngx_http_header_filter_module.c static u_char ngx_http_server_string[] = "Server: IIS" CRLF; //第49行 //修改nginx報404錯誤時,不回顯版本號,這一步也可以使用自定義404頁面代替。 [root@youxi1 nginx-1.16.0]# vim src/http/ngx_http_special_response.c "<hr><center>IIS</center>" CRLF //第36行
再之后就可以正常編譯安裝了。
//安裝依賴包 [root@youxi1 nginx-1.16.0]# yum -y install gcc gcc-c++ autoconf automake zlib zlib-devel openssl openssl-devel pcre pcre-devel [root@youxi1 nginx-1.16.0]# useradd -s /sbin/nologin -M nginx //創建一個nginx專屬用戶 [root@youxi1 nginx-1.16.0]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_gzip_static_module --with-pcre [root@youxi1 nginx-1.16.0]# make && make install [root@youxi1 nginx-1.16.0]# echo $? 0
依賴包說明:
gcc是C語言編輯器,gcc-c++是C++語言編輯器。autoconf和automake是用於configure和make編譯的工具。zlib和zlib-devel是nginx提供gzip模塊的必要支持。openssl和openssl是nginx提供ssl功能的必要支持。pcre和pcre-devel支持地址重寫(rewrite)功能。
安裝組件說明:
--user=nginx --group=nginx 設置用戶和組
--with-http_ssl_module 支持https(超文本傳輸安全協議)
--with-http_realip_module 獲取客戶端真實IP地址
--with-http_gzip_static_module 允許發送帶有.gz文件擴展名的預壓縮文件,而不是普通文件。(用於網頁壓縮調優)
--with-pcre 指定pcre庫源碼位置(源碼安裝的pcre庫需要指定詳細地址)
更多安裝組件說明可以參考:nginx編譯安裝指定參數
啟動nginx,查看是否隱藏了版本號。
[root@youxi1 nginx-1.16.0]# /usr/local/nginx/sbin/nginx [root@youxi1 nginx-1.16.0]# ps aux | grep nginx root 10639 0.0 0.1 45960 1120 ? Ss 15:03 0:00 nginx: master process /usr/local/nginx/sbin/nginx nginx 10640 0.0 0.1 46416 1884 ? S 15:03 0:00 nginx: worker process root 10642 0.0 0.0 112724 992 pts/0 R+ 15:03 0:00 grep --color=auto nginx [root@youxi1 nginx-1.16.0]# firewall-cmd --permanent --zone=public --add-port=80/tcp && firewall-cmd --reload success success [root@youxi1 nginx-1.16.0]# curl -I 192.168.5.101 HTTP/1.1 200 OK Server: IIS/7.0.0 //版本號 Date: Sun, 11 Aug 2019 07:04:31 GMT Content-Type: text/html Content-Length: 612 Last-Modified: Sun, 11 Aug 2019 06:30:28 GMT Connection: keep-alive ETag: "5d4fb604-264" Accept-Ranges: bytes
再使用Windows查看錯誤時返回的是否是修改過的版本號

(2).修改nginx運行用戶
如果編譯時已經使用--user=[username] --group=[groupname],那么其實可以不用指定了。如果編譯時沒有指定這兩個參數,那么可以修改nginx的配置文件來變更nginx的運行用戶。
[root@youxi1 nginx-1.16.0]# vim /usr/local/nginx/conf/nginx.conf user nginx; //第2行 [root@youxi1 nginx-1.16.0]# /usr/local/nginx/sbin/nginx -s reload
(3).設置nginx運行子進程個數
nginx運行子進程個數一般設置為CPU的核心數、核心數的兩倍或者auto(自動獲取),也有設置為(核心數-1)。如果CPU核心數超過8,那么nginx的進程個數設置8就差不多了,子進程個數超過8差距就不是很大了,當然設置auto讓程序自動獲取也行。
查看CPU的核心數,使用top命令,然后按1可以調出CPU核心數,我這里是4和

修改nginx運行子進程個數
[root@youxi1 ~]# vim /usr/local/nginx/conf/nginx.conf worker_processes auto; //第3行 [root@youxi1 ~]# /usr/local/nginx/sbin/nginx -s reload [root@youxi1 ~]# ps aux | grep nginx root 1138 0.0 0.0 46092 1948 ? Ss 15:21 0:00 nginx: master process /usr/local/nginx/sbin/nginx nginx 1490 0.0 0.0 46532 2004 ? S 15:30 0:00 nginx: worker process nginx 1491 0.0 0.0 46532 2004 ? S 15:30 0:00 nginx: worker process nginx 1492 0.0 0.0 46532 2004 ? S 15:30 0:00 nginx: worker process nginx 1493 0.0 0.0 46532 2004 ? S 15:30 0:00 nginx: worker process root 1497 0.0 0.0 112724 992 pts/0 S+ 15:30 0:00 grep --color=auto nginx
或者使用pstree查看nginx父進程和子進程的關系
[root@youxi1 ~]# yum -y install psmisc
[root@youxi1 ~]# pstree -p | grep nginx
|-nginx(1138)-+-nginx(1490)
| |-nginx(1491)
| |-nginx(1492)
| `-nginx(1493)
(4).設置nginx的CPU親和力
CPU的親和力,就是把nginx每個子進程綁定到固定的cpu上,從而減少cpu上下文切換導致的額外的開銷。
例如,設置nginx運行子進程個數為2,綁定的CPU為0和2。
[root@youxi1 ~]# vim /usr/local/nginx/conf/nginx.conf worker_processes 2; worker_cpu_affinity 0001 0100; //如果是8核CPU那么就要8個0。這里的0001是CPU0,0100是CPU2 [root@youxi1 ~]# /usr/local/nginx/sbin/nginx -s reload [root@youxi1 ~]# ps aux | grep nginx root 1138 0.0 0.0 46000 1968 ? Ss 15:21 0:00 nginx: master process /usr/local/nginx/sbin/nginx nginx 1566 0.0 0.0 46436 1920 ? S 16:27 0:00 nginx: worker process nginx 1567 0.0 0.0 46436 1920 ? S 16:27 0:00 nginx: worker process root 1569 0.0 0.0 112724 988 pts/0 S+ 16:27 0:00 grep --color=auto nginx [root@youxi1 ~]# taskset -cp 1566 pid 1566's current affinity list: 0 [root@youxi1 ~]# taskset -cp 1567 pid 1567's current affinity list: 2
生產環境中,如果不是極致要求一般不配值CPU親和,或者配置成auto即可。因為有可能會造成資源分配不均。
(5).設置nginx每個子進程打開的最多文件數
理論上來說,nginx子進程最多打開文件數應該是(ulimit -n)/nginx子進程個數,但是nginx分配請求並不均勻,所以可以將子進程最多打開文件數與ulimit -n的值保持一致。
[root@youxi1 ~]# ulimit -n 1024 [root@youxi1 ~]# vim /usr/local/nginx/conf/nginx.conf worker_rlimit_nofile 1024; //添加子進程個數下方 [root@youxi1 ~]# /usr/local/nginx/sbin/nginx -s reload
至於永久修改打開文件最大數量,請查看:Linux系統調優——磁盤I/O(三)
(6).nginx事件處理模型
1)epoll事件處理模型
select,poll,epoll都是nginx下的I/O多路復用機制。I/O多路復用就通過一種機制,可以監視多個描述符,一旦某個描述符就緒(一般是讀就緒或者寫就緒),能夠通知程序進行相應的讀寫操作。Epoll 在Linux2.6內核中正式引入,和select和poll相似,其實都是I/O多路復用技術。
epoll的優勢:1、Epoll沒有最大並發連接的限制,上限是最大可以打開文件的數目,這個數字一般遠大於2048, 一般來說這個數目和系統內存關系很大,具體數目可以cat /proc/sys/fs/file-max察看。2、效率提升,Epoll最大的優點就在於它只管你“活躍”的連接,而跟連接總數無關,因此在實際的網絡環境中,Epoll的效率就會遠遠高於select和poll。3、Epoll在這點上使用了“共享內存”,更省內存,效率更高。
2)如何修改nginx事件處理模型
[root@youxi1 ~]# vim /usr/local/nginx/conf/nginx.conf
events { //在文件開頭部分有一個events,在內部添加事件處理模型
use epoll; //nginx默認就是epoll
worker_connections 1024; //這個是單個子進程並發數量
}
[root@youxi1 ~]# /usr/local/nginx/sbin/nginx -s reload
(7).設置nginx最大並發量
與nginx設置事件處理模型位置一樣,里面的worker_connections是單個子進程並發數量。想要設置nginx最大並發量,就是通過設置單個子進程並發數量和子進程個數來實現。最大並發=單個子進程並發*子進程個數。
[root@youxi1 ~]# vim /usr/local/nginx/conf/nginx.conf
events {
use epoll;
worker_connections 1024; //修改這個參數值
}
[root@youxi1 ~]# /usr/local/nginx/sbin/nginx -s reload
worker_connections是指單個工作進程可以允許同時建立外部連接的數量。無論這個連接是外部主動建立的,還是內部建立的。一個工作進程建立一個連接后,進程將打開一個文件副本。所以這個數量還受限於,操作系統ulimit -n設定的值和nginx的worker_rlimit_nofile的值。一般情況下系統ulimit -n、worker_rlimit_nofile 、最大並發量三者的值是一樣的(如果三者不太一致,使用過程中它會以最小的值應用)。
(8).server_name匹配
server_name是http{}里的server{}里的一個參數,是為虛擬服務器提供識別路徑。例如,一台服務器上配置了兩個虛擬服務器,通過server_name匹配到特定的server塊,之后轉到對應的目錄或應用服務器。
server_name的匹配方法:
1、精准匹配:www.baidu.com
2、通配符匹配:*.baidu.com或www.baidu.*
3、正則表達式匹配:~ ^.*\.baidu\.com$ (~表示區分大小寫的正則匹配;~*表示不區分大小寫的正則匹配)
4、default或default_server
5、IP地址
優先級:精確匹配>左通配符匹配(*.baidu.com)>右通配符匹配(www.baidu.*)>正則表達式匹配>default或default_server。當優先級相同時,遵循自上而下的標准匹配。
修改server_name的localhost為default
[root@youxi1 ~]# vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name default;
location / {
root html;
index index.html index.htm;
}
[root@youxi1 ~]# /usr/local/nginx/sbin/nginx -t //檢測nginx配置文件是否正確
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
(9).location{}匹配
語法規則:location [ = | ~ | ~* | ^~ ] /uri/ {...}
語法說明:=表示精確匹配(絕對匹配);~表示區分大小寫的正則匹配;~*表示不區分大小寫的正則匹配;^~表示URI前半部分匹配,不檢測正則(例如:由於nginx不對url做編碼,因此請求為/static/20%/aa,可以被規則^~ /static/ /aa匹配到(注意空格));!~和!~*是~和~*相反的意思,表示不匹配;另外還有一個最特殊的,當只有一個/時,表示通配,任何請求都會匹配到。
實例說明
[root@youxi1 ~]# vim /usr/local/nginx/conf/nginx.conf
#location ~ \.php$ { //這個就表示匹配以.php結尾。\.是轉義。
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
(10).開啟高效傳輸模式
高效傳輸模式設置是在http{}下,一般處在開頭。
[root@youxi1 ~]# vim /usr/local/nginx/conf/nginx.conf
include mime.types; //媒體類型,conf目錄下的mime.types文件
default_type application/octet-stream; //默認媒體類型
sendfile on; //開啟高效傳輸模式
tcp_nopush on; //必須在sendfile開啟模式下才有效,防止網絡堵塞,積極的減少網絡報文段的數量
sendfile參數指定nginx是否調用sendfile函數來輸出文件,對於普通應用設為on,如果用來下載等應用磁盤I/O重負擔應用,可設置為off。
(11).連接超時時間
主要目的是保護服務器資源,CPU,內存,控制連接數,因為建立連接也是需要消耗資源的,TCP的三次握手四次揮手等,我們一般斷掉的是那些建立連接但是不做事的,也就是從建立了鏈接開始,但是后續的握手過程沒有進行,那么我們的鏈接處於等待狀態的,全部斷掉。另外,php建議短連接。
連接超時設置是在http{}下,一般處在開頭。
[root@youxi1 ~]# vim /usr/local/nginx/conf/nginx.conf
keepalive_timeout 65; //緊跟該行
tcp_nodelay on;
client_header_timeout 15;
client_body_timeout 15;
send_timeout 15;
參數說明:
keepalived_timeout客戶端連接保持會話超時時間,超過這個時間,服務器斷開這個鏈接。
tcp_nodelay也是防止網絡阻塞,不過要包涵在keepalived參數才有效。
client_header_timeout客戶端請求頭讀取超時時間,如果超過設個時間沒有發送任何數據,nginx將返回request time out的錯誤。
client_body_timeout客戶端求主體超時時間,超過這個時間沒有發送任何數據,和上面一樣的錯誤提示。
send_timeout響應客戶端超時時間,這個超時時間僅限於兩個活動之間的時間,如果超過這個時間,客戶端沒有任何活動,nginx關閉連接。
(12).文件上傳限制大小
在http{}頭部添加
[root@youxi1 ~]# vim /usr/local/nginx/conf/nginx.conf
http{
......
client_max_body_size 10m; //上限10M
......
}
