前面我們聊了下了Nginx作為WEB服務器對客戶端請求相關配置,文件操作優化、Nginx訪問控制、basic驗證,、狀態模塊狀態頁、gzip壓縮配置;回顧請參考https://www.cnblogs.com/qiuhom-1874/p/12381331.html;今天我們來聊一聊日志模塊、ssl模塊、rewrite模塊;
一、ngx_http_log_module:此模塊作用是指定nginx的訪問日志格式;
log_format name [escape=default|json|none] string ...;此指令就是用來定義ngxin訪問日志的格式,其中escape這個參數允許設置在變量中轉義的json或默認字符,默認情況下使用默認轉義,none表示禁止轉義。string可以使用nginx核心模塊及其它模塊內嵌的變量;注意這個指令只用於http配置段中,用於定義日志格式,后面對所有虛擬主機都可以在定義日志文件時可以調用定義的日志格式;
access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];指定日志文件路徑,其中buffer=size表示指定日志緩沖區大小,gzip=level表示指定日志壓縮級別,fulsh=time表示指定日志每隔多久就把緩沖區的日志內容存到磁盤文件中去;
示例:
提示:以上配置表示定義一個日志格式其名稱是 main ,后面用單引號引起來的部分就是日志格式內容,其中$remote_addr表示客戶端ip這個值不一定是客戶端ip,這個要看應用環境,如果nginx服務器前面有代理服務器,這個變量就會記錄前端代理的ip,如果nginx是直接面向客戶端,那么這個值就是記錄客戶端ip,具體它記錄那個ip 這個要看應用環境;$remote_user表示遠端用戶,如果我們配置的網站有驗證的話,這個值就是記錄的是用於驗證的用戶名,如果沒有則默認就是“-”;$time_local表示本地服務器時間;$request表示客戶端使用的方法請求資源路徑,以及http協議版本;$status這個變量記錄客戶端請求服務器資源時的響應狀態碼;$body_bytes_sent這個變量記錄客戶端訪問服務器時響應體的字節數,這個字節數不包含響應頭部;$http_referer此變量記錄客戶端的referer信息;referer是http頭部的一部分,通常情況下客戶端瀏覽器訪問web服務器時,都會把這個referer信息帶上,目的是告訴服務器本次請求是從那個頁面鏈接過來的;$http_user_agent此變量記錄客戶端的User_Agent信息,User_Agent也是http頭部的一部分,客戶端訪問web服務器時會帶上這個信息,目的就是告訴服務器客戶端的操作系統類型,版本,瀏覽器信息等;$http_x_forwarded_for這個變量用於記錄客戶端真實IP,如果客戶端是通過代理訪問本服務器,那么這個值不是記錄代理客戶端的IP,而是客戶端真實IP信息;更多內建變量可參考http://nginx.org/en/docs/http/ngx_http_core_module.html#variables,其他變量請參考官方文檔http://nginx.org/en/docs/varindex.html
定義好上面的日志格式,我們可以通過access_log 來指定存放日志的文件路徑並明確指定用我們定義的日志格式“main”,當我們瀏覽器訪問web服務器時,服務端就會以我們定義的格式記錄日志,如下所示
open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time];指定緩存各日志文件相關的元數據信息;其中max=N表示緩存的最大文件描述符數量,如果滿了就用LRU算法清理緩存;inactive=time表示指定非活動時長,默認情況下,10秒;min_user=N表示在inactive指定的時長內訪問大於等於此值方可被當作活動項;;vaild=time指定驗正緩存中各緩存項是否為活動項的時間間隔;
二、ngx_http_ssl_module:此模塊實現nginx基於https提供web服務
ssl on | off;啟用或禁用ssl功能
ssl_certificate file;設置當前虛擬主機的證書
ssl_certificate_key file;設置當前虛擬主機證書私鑰文件
ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2];支持ssl協議版本,默認為后三個;
ssl_session_cache off | none | [builtin[:size]] [shared:name:size];其中builtin[:size]表示使用OpenSSL內建的緩存,此緩存為每worker進程私有;[shared:name:size]:表示在各worker之間使用一個共享的緩存;
ssl_session_timeout time;客戶端一側的連接可以復用ssl session cache中緩存 的ssl參數的有效時長;
示例:
要讓nginx工作為https服務器,首先我們要對其申請證書,有關CA服務器搭建,以及證書申請相關原理說明請參考https://www.cnblogs.com/qiuhom-1874/p/12237944.html,這里說下過程,首先我們要准備一台CA(可以是本機),然后在nginx服務器上生成證書申請文件,然后把該文件發送給CA服務器,然后CA服務器簽發證書申請文件生成對應的證書,然后CA把簽好的證書文件發給nginx服務器,然后nginx服務器拿到證書后在配置文件中配置使用證書即可,當然以上步驟也可以直接在CA上做,最后把生成的私鑰文件和證書發送給nginx服務器,過程入下;
1、搭建CA,其實很簡單,所謂CA就是生成一個自簽名證書即可
[root@test ~]# cd /etc/pki/CA/ [root@test CA]# tree . ├── certs ├── crl ├── newcerts └── private 4 directories, 0 files [root@test CA]# (umask 077;openssl genrsa -out private/cakey.pem 2048) Generating RSA private key, 2048 bit long modulus ...+++ ...................+++ e is 65537 (0x10001) [root@test CA]# tree . ├── certs ├── crl ├── newcerts └── private └── cakey.pem 4 directories, 1 file [root@test CA]#
提示:以上是生成CA私鑰
2、生成自簽名證書
[root@test CA]# openssl req -new -x509 -key private/cakey.pem -out cacert.pem -days 3650 You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [XX]:CN State or Province Name (full name) []:SICHUAN Locality Name (eg, city) [Default City]:GUANGYUAN Organization Name (eg, company) [Default Company Ltd]:TEST Organizational Unit Name (eg, section) []:DEVOPS Common Name (eg, your name or your server's hostname) []:ca.ilinux.io Email Address []: [root@test CA]# touch index.txt [root@test CA]# echo 01 >serial [root@test CA]# tree . ├── cacert.pem ├── certs ├── crl ├── index.txt ├── newcerts ├── private │ └── cakey.pem └── serial 4 directories, 4 files [root@test CA]#
提示:到此CA就准備好了
3、准備nginx服務器證書私鑰和服務器證書申請文件
[root@www ~]# mkdir /etc/nginx/ssl [root@www ~]# cd /etc/nginx/ssl [root@www ssl]# ls [root@www ssl]# (umask 077;openssl genrsa -out nginx.key 2048) Generating RSA private key, 2048 bit long modulus .........................................+++ .......+++ e is 65537 (0x10001) [root@www ssl]# ll total 4 -rw------- 1 root root 1679 Mar 2 23:06 nginx.key [root@www ssl]# openssl req -new -key nginx.key -out nginx.csr You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [XX]:CN State or Province Name (full name) []:SICHUAN Locality Name (eg, city) [Default City]:GUANGYUAN Organization Name (eg, company) [Default Company Ltd]:TEST Organizational Unit Name (eg, section) []:DEVOPS Common Name (eg, your name or your server's hostname) []:www.ilinux.io Email Address []: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: [root@www ssl]# ll total 8 -rw-r--r-- 1 root root 1009 Mar 2 23:07 nginx.csr -rw------- 1 root root 1679 Mar 2 23:06 nginx.key [root@www ssl]#
提示:到此nginx服務器的證書申請文件就做好了,我們只需要把這個申請文件發送給CA
[root@www ssl]# scp -P 41319 nginx.csr qiuhom@192.168.0.99:/tmp/ qiuhom@192.168.0.99's password: nginx.csr 100% 1009 225.4KB/s 00:00 [root@www ssl]#
提示:如果SSH沒有工作在標准端口,用scp命令時需要用-P(大寫)指定ssh端口
4、CA簽發nginx證書
[root@test CA]# openssl ca -in /tmp/nginx.csr -out certs/nginx.pem -days 365 Using configuration from /etc/pki/tls/openssl.cnf Check that the request matches the signature Signature ok Certificate Details: Serial Number: 1 (0x1) Validity Not Before: Mar 2 15:11:02 2020 GMT Not After : Mar 2 15:11:02 2021 GMT Subject: countryName = CN stateOrProvinceName = SICHUAN organizationName = TEST organizationalUnitName = DEVOPS commonName = www.ilinux.io X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Comment: OpenSSL Generated Certificate X509v3 Subject Key Identifier: F7:76:62:31:04:D8:CE:0E:6E:CD:C5:14:05:EF:7F:E4:A5:AD:A0:91 X509v3 Authority Key Identifier: keyid:D5:61:A5:2F:BF:67:51:78:D7:5D:F8:51:F4:3C:FB:22:F9:E5:A7:3B Certificate is to be certified until Mar 2 15:11:02 2021 GMT (365 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated [root@test CA]# tree . ├── cacert.pem ├── certs │ └── nginx.pem ├── crl ├── index.txt ├── index.txt.attr ├── index.txt.old ├── newcerts │ └── 01.pem ├── private │ └── cakey.pem ├── serial └── serial.old 4 directories, 9 files [root@test CA]#
提示:我們只需要把簽好的證書發送給nginx服務器即可
[root@test CA]# scp certs/nginx.pem 192.168.0.30:/etc/nginx/ssl/ The authenticity of host '192.168.0.30 (192.168.0.30)' can't be established. ECDSA key fingerprint is SHA256:EG9nua4JJuUeofheXlgQeL9hX5H53JynOqf2vf53mII. ECDSA key fingerprint is MD5:57:83:e6:46:2c:4b:bb:33:13:56:17:f7:fd:76:71:cc. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.0.30' (ECDSA) to the list of known hosts. root@192.168.0.30's password: nginx.pem 100% 4464 2.1MB/s 00:00 [root@test CA]#
提示:到此CA的工作就完成了,接下來我們直接在nginx服務器上直接配置ngxin使用證書
[root@www conf.d]# cat login.conf server { listen 443 ssl; server_name 192.168.0.30; root /data/web/html; gzip on; gzip_types text/xml text/plain; gzip_disable Firefox; location /basic_status { stub_status; auth_basic "please input you username and passwd login"; auth_basic_user_file /etc/nginx/conf.d/.ngxpasswd; } ssl_certificate "/etc/nginx/ssl/nginx.pem"; ssl_certificate_key "/etc/nginx/ssl/nginx.key"; ssl_protocols sslv2 sslv3 tlsv1 tlsv1.1 tlsv1.2; ssl_session_cache shared:SSL:10m; } [root@www conf.d]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@www conf.d]# nginx -s reload [root@www conf.d]#
驗證:用瀏覽器訪問下看看我們配置的證書是否生效
提示:出現這個界面上正常的,因為我們的CA是自己搭建的,瀏覽器默認不認識,我們可以把CA證書導入瀏覽器就不會存在這個問題了,接下來我們把CA證書導入瀏覽器吧
提示:windows默認是通過后綴來識別文件,所以把CA證書放到windows上后需要更改為.crt為后綴即可.
導入CA的證書后,我們再來用瀏覽器訪問下我們的網站是否還會提示不是私密連接呢?
我們導入CA證書后,我們重新打開瀏覽器訪問網站,就沒有提示不是私密連接了,同時我們訪問我們網站也是基於https訪問,不再是http;以上就是nginx工作成https服務器搭建過程;
三、ngx_http_rewrite_module:此模塊用於使用PCRE正則表達式查找匹配用戶請求的URI,返回重定向和有條件地選擇配置來更改請求URI。本質上就是查找替換的過程,用戶請求的url通過正則匹配,然后用其他url或uri進行替換,隨后把新的url或uri返回給客戶端,由客戶端重新對新的URL或URI發送請求;
1、rewrite regex replacement [flag]:將用戶請求的URI基於regex所描述的模式進行檢查,匹配到時將其替換為replacement指定的新的URI;注意:如果在同一級配置塊中存在多個rewrite規則,那么會自上而下逐個檢查;被某條件規則替換完成后,會重新一輪的替換檢查,因此,隱含有循環機制;[flag]所表示的標志位用於控制此循環機制;如果replacement是以http://或https://開頭,則替換結果會直接以重向返回給客戶端;其中flag有四種,last表示重寫完成后停止對當前URI在當前location中后續的其它重寫操作,而后對新的URI啟動新一輪重寫檢查;提前重啟新一輪循環; 這個也是默認行為,有點類似continue指令的意思,不退出循環,只是退出當次循環,提前進入下次循環;break表示重寫完成后停止對當前URI在當前location中后續的其它重寫操作,而后直接跳轉至重寫規則配置塊之后的其它配置;結束循環;這個我們可以理解為循環里的break指令,直接跳出循環,進行下面的配置指令;redirect表示重寫完成后以臨時重定向方式直接返回重寫后生成的新URI給客戶端,由客戶端重新發起請求;不能以http://或https://開頭;permanent表示重寫完成后以永久重定向方式直接返回重寫后生成的新URI給客戶端,由客戶端重新發起請求;這四個值的區別是,前兩個瀏覽器上都看不到跳轉(用戶是看不到明確的跳轉),后兩者者看得到;
示例:
rewrite /(.*)$ https://www.ilinux.io/basic_status;
提示:以上配置表示客戶端訪問我們服務器的任何uri都給重寫為https://www.ilinux.io/basic_status這個url
提示:之所以能夠看到302的響應碼是因為我們在規則里把用戶的rul重寫成https://www.ilinux.io/basic_status ,瀏覽器看到重寫后的URL是以https開頭的,它就會拿着這個url去請求新的URL,所以我們這里可以看到302響應碼;
提示:以上配置表示,用戶訪問.jpg結尾的URL時,我們都對它重寫為訪問/test/test.html
提示:我們對用戶請求的url進行替換時,沒有用到http或https去替換時,我們在瀏覽器上是看不到后面瀏覽器重新對新的url發起請求的請求信息,這是我們重寫規則默認使用了last,last和break如果都不以http或https去替換用戶的rul,在瀏覽器是看不到跳轉的響應碼,要想看到該過程我們可以在后面加redirect或者permanent,它倆的區別在於,一個是臨時重定向,響應碼是302,一個是永久重定向響應碼是301;如下
rewrite /(.*)\.jpg /test/ redirect;
提示:我們只在上面的配置上在rewrite規則上加了一個redirect標記,加上它,瀏覽器就會對新的uri發起新的請求,如下
2、return:停止處理並將指定的響應碼或URL返回給客戶端
return code [text];表示返回狀態碼或簡短原因短語
return code URL;返回狀態碼和url
return URL;返回url
3、rewrite_log on | off;是否開啟重寫日志
4、if(condition) {……};引入一個新的配置上下文;條件滿足時執行配置塊中的配置指令;可用在server和location配置段中;這里的條件可以是變量,如果變量是字符串,非空為真,空為假;如果變量是數字則非0為真,0為假;當然條件也可以是一個比較表達式,所謂表達式就是由操作符連接起來的式子,常用的操作符有比較操作符,文件及目錄存在性判斷;比較操作符有:== 、!= 、~表示模式匹配,區分字符大小寫;~*表示模式匹配,不區分字符大小寫;!~表示模式不匹配,區分字符大小寫;!~*表示模式不匹配,不區分字符大小寫;文件及目錄存在性判斷的有 -e,!-e、-f,!-f、-d,!-d,、-x,!-x,這里的文件或目錄存在性判斷同shell里面的文件或目錄存在性判斷是一樣的;
5、set $variable value;設置用戶指定以變量;
示例:
if ($http_user_agent ~ MSIE) { rewrite ^(.*)$ /msie/$1 break; } if ($http_cookie ~* "id=([^;]+)(?:;|$)") { set $id $1; } if ($request_method = POST) { return 405; } if ($slow) { limit_rate 10k; } if ($invalid_referer) { return 403; }
提示:第一個if表示判斷用戶瀏覽器類型,如果匹配MSIE 則進行url重寫,重寫為/msie/$1 ,這里的$1表示rewrite規則里匹配到第一個括號里的內容的引用,和sed命令里的\1類似;第二個if表示判斷變量$http_cookie 里的值是否匹配后面的正則表達式,如果匹配則設置$id變量的值為$1,這里的$1表示正則表達式里括號分組匹配到的內容;第三個if表示判斷用戶請求的方法是否是POST,如果是就返回405,意思就是不讓用戶用POST方法提交數據;第五個if表示判斷$slow是否為空,不為空就設置limit_rate 10k,意思就是如果$slow的值為真,則限制客戶端的響應;最后一個if表示判斷$invalid_referer 是否為空,為空表示沒有非法的referer,沒有非法referer就不做處理,如果有非法referer,即不為空,則返回403,這是一個防盜鏈的配置;通常我們要先定義合法的referer,然后再來判斷非法referer來實現防盜鏈(定義了合法的referer后相對的不在合法的referer列表里就表示非法的referer);合法referer的定義可以用valid_referers來指定;