Nginx之常用基本配置(三)

  前面我們聊了下了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

  定義好上面的日誌格式,我們可以通過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 [email protected]:/tmp/  [email protected]'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.  [email protected]'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來指定;