一、高級配置
1.1網頁狀態頁
基于nginx 模塊 ngx_http_stub_status_module 實現,在編譯安裝nginx的時候需要添加編譯參數 --with-http_stub_status_module,否則配置完成之后監測會是提示語法錯誤注意: 狀態頁顯示的是整個服務器的狀態,而非虛擬主機的狀態。
狀態頁用于輸出 nginx 的基本狀態信息:
Active connections:?
#當前處于活動狀態的客戶端連接數,包括連接等待空閑連接數=reading+writing+waiting
accepts:
#統計總值,Nginx自啟動后已經接受的客戶端請求的總數。
handled:
#統計總值,Nginx自啟動后已經處理完成的客戶端請求總數,通常等于accepts,除非有因worker_connections限制等被拒絕的連接
requests:
#統計總值,Nginx自啟動后客戶端發來的總的請求數。
Reading:
#當前狀態,正在讀取客戶端請求報文首部的連接的連接數,數值越大,說明排隊現象嚴重,性能不足
Writing:
#當前狀態,正在向客戶端發送響應報文過程中的連接數,數值越大,說明訪問量很大
Waiting:
#當前狀態,正在等待客戶端發出請求的空閑連接數,開啟 keep-alive的情況下,這個值等于active – (reading+writing)
為了安全考慮,可以搭配驗證模塊一起使用
server {
? ? listen 80;
? ? server_name ?www.lucky.com;
? ? root /data/html;
? ? location /status {
? ? stub_status;
? ? auth_basic ?"welcome future";
? ? auth_basic_user_file ?/mnt/.nginxuser;
?}?
?
}
只允許自己,拒絕所有?
server {
? ? listen 80;
? ? server_name ?www.lucky.com;
? ? root /data/html;
?
? ? location /status {
? ? stub_status;
? ? auth_basic ?"welcome future";
? ? auth_basic_user_file ?/mnt/.nginxuser;
? ? allow 192.168.91.3;
? ? deny all;
}
}
1.2nginx 第三方模塊:
1.2.1echo模塊:
更改子配置文件:
編譯之前,先關閉 nginx,導入壓縮包,并解壓
[root@localhost opt]# unzip echo-nginx-module-master.zip
[root@localhost opt]# cd nginx-1.18.0/
[root@localhost nginx-1.18.0]# systemctl stop nginx
[root@localhost nginx-1.18.0]# ./configure --help | grep add
? --with-http_addition_module ? ? ? ?enable ngx_http_addition_module
? --add-module=PATH ? ? ? ? ? ? ? ? ?enable external module
[root@localhost nginx-1.18.0]# ./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --add-module=/opt/echo-nginx-module-master
[root@localhost nginx-1.18.0]# make && make install
[root@localhost nginx-1.18.0]# systemctl start nginx
1.3變量
官方文檔? ? http://nginx.org/en/docs/varindex.html
1.3.1內置變量
$remote_addr | 存放了客戶端的地址,注意是客戶端的公網IP |
$args | 變量中存放了URL中的參數 |
$document_uri | 保存了當前請求中不包含參數的URI,注意是不包含請求的指令 |
$host | 存放了請求的host名稱服務端的地址 |
$request_filename | 當前請求的資源文件的磁盤路徑,由root或alias指令與URI請求生成的文件絕對路徑 |
$scheme | 請求的協議,例如:http,https,ftp |
$http_user_agent | 客戶端瀏覽器的詳細信息 |
$http_cookie | 客戶端的cookie信息 |
$document_root | 保存了針對當前資源的請求的系統根目錄 |
$remote_addr;?
#存放了客戶端的地址,注意是客戶端的公網IP
?
?
?
?
$proxy_add_x_forwarded_for
#此變量表示將客戶端IP追加請求報文中X-Forwarded-For首部字段,多個IP之間用逗號分隔,如果請求中沒有X-Forwarded-For,就使用$remote_addrthe “X-Forwarded-For” client request header field with the $remote_addr variable appended to it, separated by a comma. If the “X-Forwarded-For” field is not present in the client request header, the $proxy_add_x_forwarded_for variable is equal to the $remote_addr variable.
客戶機 ? ?代理1 ? ? 代理2 ? ? nginx服務器
$proxy_add_x_forwarded_for: 在代理1 上存的是 ?客戶機的ip
$proxy_add_x_forwarded_for: 在代理2 上存的是 ?客戶機的ip,代理1的ip ? ? ? ? ? ?用逗號隔開
$proxy_add_x_forwarded_for: nginx ?上存的是 ?客戶機的ip,代理1的ip,代理2的ip
?
?
?
$args;?
#變量中存放了URL中的參數,例如:http://www.kgc.org/main/index.do?id=20190221&partner=search
#返回結果為: id=20190221&partner=search ? ?存放的就是這個
?
select ? * ?from table ?where id=20190221
?
?
$document_root;?
#保存了針對當前資源的請求的系統根目錄,例如:/apps/nginx/html
?
?
?
$document_uri;
#保存了當前請求中不包含參數的URI,注意是不包含請求的指令,比
如:http://www.kgc.org/main/index.do?id=20190221&partner=search會被定義為/main/index.do?
#返回結果為:/main/index.do
?
?
$host;?
#存放了請求的host名稱
服務端的地址
?
?
limit_rate 10240;
echo $limit_rate;
#如果nginx服務器使用limit_rate配置了顯示網絡速率,則會顯示,如果沒有設置, 則顯示0
?
?
$remote_port;?
#客戶端請求Nginx服務器時隨機打開的端口,這是每個客戶端自己的端口
?
$remote_user;?
#已經經過Auth Basic Module驗證的用戶名
?
$request_body_file;?
#做反向代理時發給后端服務器的本地資源的名稱
?
$request_method;?
#請求資源的方式,GET/PUT/DELETE等
?
$request_filename;?
#當前請求的資源文件的磁盤路徑,由root或alias指令與URI請求生成的文件絕對路徑,如:/apps/nginx/html/main/index.html
?
$request_uri; ? https:// www.baidu.com/main/index.do?id=20190221&partner=search?
#包含請求參數的原始URI,不包含主機名,相當于:$document_uri?$args,例如:/main/index.do?id=20190221&partner=search?
?
$scheme;?
#請求的協議,例如:http,https,ftp等
?
$server_protocol;?
#保存了客戶端請求資源使用的協議的版本,例如:HTTP/1.0,HTTP/1.1,HTTP/2.0等
?
$server_addr;?
#保存了服務器的IP地址
?
$server_name;?
#請求的服務器的主機名
?
$server_port; ?443 ?https?
#請求的服務器的端口號
?
$http_<name>
#name為任意請求報文首部字段,表示記錄請求報文的首部字段
arbitrary request header field; the last part of a variable name is the field name converted to lower case with dashes replaced by underscores?
#用下劃線代替橫線
#示例: echo $http_User_Agent; ?
?
$http_user_agent;?
#客戶端瀏覽器的詳細信息
?
$http_cookie;?
#客戶端的cookie信息
?
?
$cookie_<name>
#name為任意請求報文首部字部cookie的key名
?
$http_<name>
#name為任意請求報文首部字段,表示記錄請求報文的首部字段,ame的對應的首部字段名需要為小寫,如果有
橫線需要替換為下劃線
arbitrary request header field; the last part of a variable name is the field?
name converted to lower case with dashes replaced by underscores #用下劃線代替橫線
#示例:?
echo $http_user_agent;?
echo $http_host;
?
?
$sent_http_<name>
#name為響應報文的首部字段,name的對應的首部字段名需要為小寫,如果有橫線需要替換為下劃線,此變量有問題
echo $sent_http_server;
?
?
?
$arg_<name>
#此變量存放了URL中的指定參數,name為請求url中指定的參數
#對比 變量 ?$arg ?是全部, 如果 要id ? 如下
echo $arg_id;
1.3.2自定義變量
假如需要自定義變量名稱和值,使用指令 set $variable value;
1.4自定義訪問日志
1.4.1日志的格式可以指定
訪問日志是記錄客戶端即用戶的具體請求內容信息,而在全局配置模塊中的 error log 是記錄 nginx服務器運行時的日志保存路徑和記錄日志的 level,因此兩者是不同的,而且Nginx的錯誤日志一般只有一個,但是訪問日志可以在不同 server 中定義多個,定義一個日志需要使用 access_log 指定日志的保存路徑,使用 log_format 指定日志的格式,格式中定義要保存的具體日志內容。
訪問日志由 ngx_http_log_module 模塊實現
Syntax: access_log path [format [buffer=size] [gzip[=level]] (flush=time] [if=condition]];access_log off;
Defau1t:
access_log 1ogs/access.1og combined;
Context: http,server, location,if in location,limit_except
log_format ?main ?'$remote_addr - $remote_user [$time_local] "$request" '
? ? ? ? ? ? ? ? ? ? ? '$status $body_bytes_sent "$http_referer" '
? ? ? ? ? ? ? ? ? ? ? '"$http_user_agent" "$http_x_forwarded_for"'
? ? ? ? ? ? ? ? ? ? ? '$server_name:$server_port';
?
?
log_format ?test ?'$remote_addr - $remote_user [$time_local] "$request" '
? ? ? ? ? ? ? ? ? ? ? '$status $body_bytes_sent "$http_referer" '
? ? ? ? ? ? ? ? ? ? ? '"$http_user_agent" "$http_x_forwarded_for"'
? ? ? ? ? ? ? ? ? ? ? '$server_name:$server_port';
?
格式可以定義多個
?
###注意如果開啟 include ?注意定義自配置文件與 日志格式的上下關系 ?, ? 日志格式一定要在 ?include 之前 否則會不生效。
查看
1.4.2自定義 json 格式日志
可以配置它以輸出自定義的JSON格式日志。這種格式對于日志記錄和后續分析非常有用,因為JSON格式易于解析并且適合于許多日志分析工具,如方便ELK收集日志。
修改主配置文件:
[root@localhost ~]# vim /apps/nginx/conf/nginx.conf?
?30 ? ? log_format access_json '{"@timestamp":"$time_iso8601",'
?31 ? ? ? ? '"host":"$server_addr",'
?32 ? ? ? ? '"clientip":"$remote_addr",'
?33 ? ? ? ? '"size":$body_bytes_sent,'
?34 ? ? ? ? '"responsetime":$request_time,'
?35 ? ? ? ? '"upstreamtime":"$upstream_response_time",'
?36 ? ? ? ? '"upstreamhost":"$upstream_addr",' ?
?37 ? ? ? ? '"http_host":"$host",'
?38 ? ? ? ? '"uri":"$uri",'
?39 ? ? ? ? '"xff":"$http_x_forwarded_for",'
?40 ? ? ? ? '"referer":"$http_referer",'
?41 ? ? ? ? '"tcp_xff":"$proxy_protocol_addr",'
?42 ? ? ? ? '"http_user_agent":"$http_user_agent",'
?43 ? ? ? ? '"status":"$status"}';
?44 ? ? access_log ?logs/access.log ?access_json;
?查看json格式日志:
{"@timestamp":"2024-02-25T21:54:30+08:00", ? ?'"host":"192.168.190.102",' ? ?'"clientip":"192.168.190.100",' ? ?'"size":612,' ? ?'"responsetime":0.000,' ? ?'"upstreamtime":"-",' ? ?'"upstreamhost":"-",' ? ? '"http_host":"192.168.190.102",' ? ?'"uri":"/index.html",' ? ?'"xff":"-",' ? ?'"referer":"-",' ? ?'"tcp_xff":"-",' ? ?'"http_user_agent":"curl/7.29.0",' ? ?'"status":"200"}'
1.4.3日志分割
----------------日志切割-------------------
vim /opt/fenge.sh
#!/bin/bash
# Filename: fenge.sh
day=$(date -d "-1 day" "+%Y%m%d")?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?#顯示前一天的時間
logs_path="/var/log/nginx"
pid_path="/usr/local/nginx/logs/nginx.pid"
[ -d $logs_path ] || mkdir -p $logs_path ?? ??? ??? ??? ??? ??? ??? ??? ??? ?#創建日志文件目錄
mv /usr/local/nginx/logs/access.log ${logs_path}/kgc.com-access.log-$day?? ?#移動并重命名日志文件
kill -USR1 $(cat $pid_path)?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?#重建新日志文件
find $logs_path -mtime +30 -exec rm -rf {} \;?? ??? ??? ??? ??? ??? ??? ??? ?#刪除30天之前的日志文件
#find $logs_path -mtime +30 | xargs rm -rf?
?
?
?
chmod +x /opt/fenge.sh
/opt/fenge.sh
ls /var/log/nginx
ls /usr/local/nginx/logs/access.log?
?
#設置周期計劃任務
crontab -e
0 1 * * * /opt/fenge.sh
1.5nginx壓縮
支持對指定類型的文件進行壓縮然后再傳輸給客戶端,而且壓縮還可以設置壓縮比例,壓縮后的文件大小將比源文件顯著變小,這樣有助于降低出口帶寬的利用率,降低企業的IT支出,不過會占用相應的CPU資源。Nginx對文件的壓縮功能是依賴于模塊? ngx_http_gzip_module
#啟用或禁用gzip壓縮,默認關閉
gzip on | off;?
?
?
#壓縮比由低到高從1到9,默認為1
gzip_comp_level level;
?
?
#禁用IE6 gzip功能
gzip_disable "MSIE [1-6]\.";?
?
?
#gzip壓縮的最小文件,小于設置值的文件將不會壓縮
gzip_min_length 1k;?
?
?
#啟用壓縮功能時,協議的最小版本,默認HTTP/1.1
gzip_http_version 1.0 | 1.1;?
?
?
#指定Nginx服務需要向服務器申請的緩存空間的個數和大小,平臺不同,默認:32 4k或者16 8k;
gzip_buffers number size;?
?
?
#指明僅對哪些類型的資源執行壓縮操作;默認為gzip_types text/html,不用顯示指定,否則出錯
gzip_types mime-type ...; ? ??
?
?
#如果啟用壓縮,是否在響應報文首部插入“Vary: Accept-Encoding”,一般建議打開
gzip_vary on | off;
?
?
#預壓縮,先壓縮好,不用臨時壓縮,消耗cpu
gzip_static on | off;‘
1.5.1實際操作
太小的文件沒必要壓縮,壓縮說不定變大了
測試
如果不是 200,按ctrl強制刷新:
1.5.2預壓縮
gzip_static on | off??? 預壓縮,先壓縮好,不用臨時壓縮,消耗cpu
更改配置文件:
更改子配置文件:
壓縮文件:?
[root@localhost data]# gzip index.html
[root@localhost data]# ls
index.html.gz
[root@localhost data]# mv index.html.gz m.html.gz
測試
1.6https功能
Web網站的登錄頁面都是使用https加密傳輸的,加密數據以保障數據的安全,HTTPS能夠加密信息,以免敏感信息被第三方獲取,所以很多銀行網站或電子郵箱等等安全級別較高的服務都會采用HTTPS協議,HTTPS其實是有兩部分組成:HTTP + SSL / TLS,也就是在HTTP上又加了一層處理加密信息的模塊。服務端和客戶端的信息傳輸都會通過TLS進行加密,所以傳輸的數據都是加密后的數據。
過程:
1.客戶端發起HTTPS請求
用戶在瀏覽器里輸入一個 https 網址,然后連接到服務器的 443 端口
2.服務端的配置
采用HTTPS協議的服務器必須要有一套數字證書,可以自己制作,也可以向組織申請,區別就是自己頒發的證書需要客戶端驗證通過,才可以繼續訪問,而使用受信任的公司申請的證書則不會彈出提示頁面。這套證書其實就是一對公鑰和私鑰
3.傳送服務器的證書給客戶端
證書里其實就是公鑰,并且還包含了很多信息,如證書的頒發機構,過期時間等等
4.客戶端解析驗證服務器證書
這部分工作是由客戶端的TLS來完成的,首先會驗證公鑰是否有效,比如:頒發機構,過期時間等等,如果發現異常,則會彈出一個警告框提示證書存在問題。如果證書沒有問題,那么就生成一個隨機值,然后用證書中公鑰對該隨機值進行非對稱加密
5.客戶端將加密信息傳送服務器
這部分傳送的是用證書加密后的隨機值,目的就是讓服務端得到這個隨機值,以后客戶端和服務端的通信就可以通過這個隨機值來進行加感解密了
6. 服務端解密信息
服務端將客戶端發送過來的加密信息用服務器私鑰解密后,得到了客戶端傳過來的隨機值
7.服務器加密信息并發送信息
服務器將數據利用隨機值進行對稱加密,再發送給客戶端
8.客戶端接收并解密信息
客戶端用之前生成的隨機值解密服務段傳過來的數據,于是獲取了解密后的內容
nginx 的 https 功能基于模塊 ngx_http_ssl_module 實現,因此如果是編譯安裝的nginx要使用參數 ngx_http_ssl_module 開啟 ssl 功能,但是作為 nginx 的核心功能,yum安裝的 nginx 默認就是開啟的,編譯安裝的nginx需要指定編譯參數 --with-http_ssl_module 開啟
ssl on | off; ??
#為指定的虛擬主機配置是否啟用ssl功能,此功能在1.15.0廢棄,使用listen [ssl]替代
listen 443 ssl;
?
ssl_certificate /path/to/file;
#指向包含當前虛擬主機和CA的兩個證書信息的文件,一般是crt文件
?
ssl_certificate_key /path/to/file;
#當前虛擬主機使用的私鑰文件,一般是key文件
?
ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2];?
#支持ssl協議版本,早期為ssl現在是TLS,默認為后三個
?
ssl_session_cache off | none | [builtin[:size]] [shared:name:size];
#配置ssl緩存
?off: #關閉緩存
?none: ?#通知客戶端支持ssl session cache,但實際不支持
?builtin[:size]:#使用OpenSSL內建緩存,為每worker進程私有
?[shared:name:size]:#在各worker之間使用一個共享的緩存,需要定義一個緩存名稱和緩存空間大小,一兆可以存儲4000個會話信息,多個虛擬主機可以使用相同的緩存名稱
?
ssl_session_timeout time;
#客戶端連接可以復用ssl session cache中緩存的有效時長,默認5m
?編譯安裝的nginx需要指定編譯參數?--with-http_ssl_module?開啟
1.6.1自簽名證書
#所有的證書需要放在一起不能移開
?
bash certificate.sh
?
cat kgc.com.crt ca.crt > www.kgc.com.crt
#kgc.com.crt(購買者)
#ca.crt(頒發者)
?
mv kgc.com.key ?www.kgc.com.key
#www.kgc.com.key(驗證鑰匙)
[root@localhost ~]# cd /data
[root@localhost data]# ls
[root@localhost data]# mkdir ssl
[root@localhost data]# cd ssl/
[root@localhost ssl]# rz -E
rz waiting to receive.
[root@localhost ssl]# ls
certificate.sh
[root@localhost ssl]# bash certificate.sh?
[root@localhost ssl]# ls
ca.crt ?ca.key ?certificate.sh ?kgc.com.crt ?kgc.com.csr ?kgc.com.key
[root@localhost ssl]# cat kgc.com.crt ca.crt > www.kgc.com.crt
[root@localhost ssl]# mv kgc.com.key www.kgc.com.key
[root@localhost ssl]# ll www*
-rw-r--r--. 1 root root 2201 2月 ?26 10:25 www.kgc.com.crt
-rw-------. 1 root root 1704 2月 ?26 10:23 www.kgc.com.key
生成私鑰工具:?
更改子配置文件:?
測試
二、重寫功能rewrite
Nginx服務器利用 ngx_http_rewrite_module 模塊解析和處理rewrite請求,此功能依靠 PCRE(perl compatible regular expression),因此編譯之前要安裝PCRE庫,rewrite是nginx服務器的重要功能之一,用于實現URL的重寫,URL的重寫是非常有用的功能,比如它可以在我們改變網站結構之后,不需要客戶端修改原來的書簽,也無需其他網站修改我們的鏈接,就可以設置為自動訪問,另外還可以在一定程度上提高網站的安全性。
2.1ngx_http_rewrite_module模塊指令:
2.1.1if指令
用于條件匹配判斷,并根據條件判斷結果選擇不同的Nginx配置,可以配置在server或location塊中進行配置,Nginx的if語法僅能使用if做單次判斷,不支持使用if else或者if elif這樣的多重判斷,用法如下:
格式
if (條件匹配) { ??
?action
}
使用正則表達式對變量進行匹配,匹配成功時if指令認為條件為true,否則認為false,變量與表達式之間使用以下符號鏈接:
=?
#比較變量和字符串是否相等,相等時if指令認為該條件為true,反之為false
!= ?
#比較變量和字符串是否不相等,不相等時if指令認為條件為true,反之為false
?
?
~?
#區分大小寫字符,可以通過正則表達式匹配,滿足匹配條件為真,不滿足匹配條件為假
!~?
#區分大小寫字符,判斷是否匹配,不滿足匹配條件為真,滿足匹配條件為假
?
?
~*?
#不區分大小寫字符,可以通過正則表達式匹配,滿足匹配條件為真,不滿足匹配條件為假
!~*?
#不區分大小字符,判斷是否匹配,滿足匹配條件為假,不滿足匹配條件為真
?
?
-f 和 !-f #判斷請求的文件是否存在和是否不存在
?
-d 和 !-d #判斷請求的目錄是否存在和是否不存在
?
-x 和 !-x #判斷文件是否可執行和是否不可執行
?
-e 和 !-e #判斷請求的文件或目錄是否存在和是否不存在(包括文件,目錄,軟鏈接)
location /main {
? ? ?index index.html;
? ? ?default_type text/html;
? ? ?if ( $scheme = http ){
? ? ? ?echo "if-----> $scheme";
? ? ?}
? ? ?if ( $scheme = https ){
? ? ? echo "if ----> $scheme";
? ?}
? ??
? ? ?#if (-f $request_filename) {
? ? ?# ? echo "$request_filename is exist";
? ? ?#}
? ? ?if (!-e $request_filename) {
? ? ? ? echo "$request_filename is not exist";
? ? ? ? #return ;
? ?}
?}
示例
2.1.2return指令
return用于完成對請求的處理,并直接向客戶端返回響應狀態碼,比如:可以指定重定向URL(對于特殊重定向狀態碼,301/302等) 或者是指定提示文本內容(對于特殊狀態碼403/500等),處于此指令后的所有配置都將不被執行,return可以在server、if 和 location塊進行配置
語法格式:
www.pc.com/test/
404
return code; #返回給客戶端指定的HTTP狀態碼
return code [text]; #返回給客戶端的狀態碼及響應報文的實體內容,可以調用變量,其中text如果有空格,需要用單或雙引號
return code url; #返回給客戶端的URL地址
? ? location /main {
? ? index index.html;
? ? default_type text/html;
? ? if ( $scheme = http ){
? ? return 666 "if-----> $scheme"; ? ?#如果是http的 ?打印http
? ?}
? ? if (!-e $request_filename){
? ? return 302 ?/index.html; ? ? ? ? ?#如果用戶不存在,返回302,直接跳轉到主頁面
?
}
任意跳轉:
? ? location / {
? ? root ?/data;
? ? if (!-e $request_filename){
? ? ? return 302 ?http://www.baidu.com;
}
}
如果訪問不存在就跳轉到百度
測試
301 和 302區別:
301 永久重定向? 讀取過一次,就會將此條配置緩存在我們的客戶端,即使 nginx?服務器宕機,在緩存時間內,還是可以跳轉。
302 臨時重定向??不會有緩存在客戶端,每次跳轉需要 nginx 服務器解析,一旦服務器宕機就無法跳轉
?自定義內容:
2.1.3set?指令:
指定key并給其定義一個變量,變量可以調用Nginx內置變量賦值給key,另外set定義格式為set $key value,value可以是text, variables和兩者的組合。
location /main {
? ?root /data/nginx/html/pc;
? ?index index.html;
? ?default_type text/html;
? ? set $name kgc;
? ? echo $name;
? ? set $my_port $server_port(nginx ?自帶的變量 ?服務端口 一般80);
? ? echo $my_port;
}
實例
2.1.4break
用于中斷當前相同作用域(location)中的其他Nginx配置,與該指令處于同一作用域的Nginx配置中,位于它前面的配置生效,位于后面的 ngx_http_rewrite_module 模塊中指令就不再執行,Nginx服務器在根據配置處理請求的過程中遇到該指令的時候,回到上一層作用域繼續向下讀取配置,該指令可以在server塊和locationif塊中使用。
注意: 如果break指令在location塊中后續指令還會繼續執行,只是不執行 ngx_http_rewrite_module 模塊的指令,其它指令還會執行
location /main {
? ?root /data/nginx/html/pc;
? ?index index.html;
? ?default_type text/html;
? ? set $name kgc;
? ? echo $name;
? ?break; ?#location塊中break后面指令還會執行
? ? set $my_port $server_port;
? ? echo $my_port;
?}
示例
注意:?如果break指令在location塊中后續指令還會繼續執行,只是不執行 ngx_http_rewrite_module 模塊的指令,其它指令還會執行。
2.2rewrite :
通過正則表達式的匹配來改變URI,可以同時存在一個或多個指令,按照順序依次對URI進行匹配,rewrite主要是針對用戶請求的URL或者是URI做具體處理.
語法格式:
rewrite可以配置在 server、location、if
語法格式 :
rewrite regex ? ? ? ? ? ? ? replacement(www.baidu.com) ? ? ? ?[flag];
? ? ? ? 正則匹配原始訪問url ? ?替代你想讓客戶訪問的 ? ? ? ? ? ? ? ? 標志 ?()premanent301 ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? redirect302 ?break ?last
rewrite?將用戶請求的URI基于regex所描述的模式進行檢查,匹配到時將其替換為表達式指定的新的URI
正則表達式格式:
. ?#匹配除換行符以外的任意字符
\w #匹配字母或數字或下劃線或漢字
\s #匹配任意的空白符
\d #匹配數字 ? ?[0-9] ? ? ?。。
\b #匹配單詞的開始或結束
^ #匹配字付串的開始
$ #匹配字符串的結束
* #匹配重復零次或更多次
+ #匹配重復一次或更多次
? #匹配重復零次或一次
{n} #匹配重復n次
{n,} #匹配重復n次或更多次
{n,m} #匹配重復n到m次
*? #匹配重復任意次,但盡可能少重復
+? #匹配重復1次或更多次,但盡可能少重復
?? #匹配重復0次或1次,但盡可能少重復
{n,m}? #匹配重復n到m次,但盡可能少重復
{n,}? #匹配重復n次以上,但盡可能少重復
\W ?#匹配任意不是字母,數字,下劃線,漢字的字符
\S #匹配任意不是空白符的字符
\D #匹配任意非數字的字符
\B #匹配不是單詞開頭或結束的位置
[^g] #匹配除了g以外的任意字符
[^gg] #匹配除了gg 這幾個字母以外的任意字符
rewrite flag 使用介紹
利用nginx的rewrite的指令,可以實現url的重新跳轉,rewrtie有四種不同的flag,分別是 redirect(臨時重定向302)、permanent(永久重定向301)、break和last。其中前兩種是跳轉型的flag,后兩種是代理型。
-
跳轉型指由客戶端瀏覽器重新對新地址進行請求
-
代理型是在web服務器內部實現跳轉
redirect;302
#臨時重定向,重寫完成后以臨時重定向方式直接返回重寫后生成的新URL給客戶端,由客戶端重新發起請求;使用相對路徑,或者http://或https://開頭,狀態碼:302
?
permanent;301 ? ? ??
#重寫完成后以永久重定向方式直接返回重寫后生成的新URL給客戶端,由客戶端重新發起請求,狀態碼:301
?
?
?
break; ? ??
#重寫完成后,停止對當前URL在當前location中后續的其它重寫操作,而后直接跳轉至重寫規則配置塊之后的其它配置;結束循環,建議在location中使用
#適用于一個URL一次重寫 ??
#一次匹配
?
?
?
?
last;
#重寫完成后,停止對當前URI在當前location中后續的其它重寫操作,而后對新的URL啟動新一輪重寫檢查,不建議在location中使用
#適用于一個URL多次重寫,要注意避免出現超過十次以及URL重寫后返回錯誤的給用戶301
#多次匹配
?實例:
更改子配置文件:
?創建所需文件夾:
案例:http 轉https :?
?針對全站跳轉:
location / { ? ? ? ? ? ? ? ? ? #針對全站跳轉
? ?if ( $scheme = http ) { ? ? ? ? ?#如果不加條件判斷,會導致死循環
? rewrite ?/(.*) ?https://$host/$1 ?permanent;
}
}
?last 與 break:
location /break { ? ? ? ? ? #訪問break
rewrite .* /test break; ? ? #重寫到test
}
?
location /last { ? ? ? ? ? ?#訪問break?
rewrite .* /test last; ? ? ?#重寫到test
}
?
location /test {
rewrite 403; ? ? ? ? ? ? ? ?#last返回403,因為last會多次匹配
}
說明:?
redirect;302:臨時重定向,重寫完成后以臨時重定向方式直接返回重寫后生成的新URL給客戶端,由客戶端重新發起請求;使用相對路徑,或者http://或https://開頭,狀態碼:302
permanent;301:重寫完成后以永久重定向方式直接返回重寫后生成的新URL給客戶端,由客戶端重新發起請求,狀態碼:301
break:重寫完成后,停止對當前URL在當前location中后續的其它重寫操作,而后直接跳轉至重寫規則配置塊之后的其它配置;結束循環,建議在location中使用,適用于一個URL一次重寫?
last:重寫完成后,停止對當前URI在當前location中后續的其它重寫操作,而后對新的URL啟動新一輪重寫檢查,不建議在location中使用。適用于一個URL多次重寫,要注意避免出現超過十次以及URL重寫后返回錯誤的給用戶301。
案例1:更換目錄訪問方式,目錄轉化為對象存儲形式:
要求:
/20200106/static->/static?id=20200106
/20200123/image ->/image?id=20200123
方法:
rewrite ?^/(\d+)/(.+)/ ? /$2?id=$1 ?break;
\d+:一個以上數字;.+:一個以上的字符
案例2:多目錄轉換訪問方式:
要求:
www.lucky.com/images/20200106/1.jpg => www.lucky.com/index.do?name=images&dir=20200106=&fi1e=1.jpg?
規則配置:
if($host ~* ?(.*)\.lucky\.com) {
rewrite ?^/(.*)/(\d+)/(.*)$ ? /index.do?name=$1&dir=$2&file=$3 last;}
示例
2.3防盜鏈
防盜鏈基于客戶端攜帶的 referer 實現,referer 是記錄打開一個頁面之前記錄是從哪個頁面跳轉過來的標記信息,如果別人只鏈接了自己網站圖片或某個單獨的資源,而不是打開了網站的整個頁面,這就是盜鏈,referer 就是之前的那個網站域名,正常的 referer 信息有以下幾種:
none: ?#請求報文首部沒有 referer 首部,
比如用戶直接在瀏覽器輸入域名訪問web網站,就沒有referer信息。
?
blocked: #請求報文有 referer 首部,但無有效值,
比如為空。
?
server_names: #referer首部中包含本主機名及即nginx 監聽的server_name。
?
arbitrary_string: #自定義指定字符串,但可使用*作通配符。
示例: *.kgc.org www.kgc.*
?
regular expression:#被指定的正則表達式模式匹配到的字符串,要使用~開頭
示例: ~.*\.kgc\.com
.被盜端添加文件a.jpg:
[root@localhost data]# ls
a.jpg ?beijing ?favicon.ico ?index.html ?ssl
2. 盜取端開啟httpd服務,添加web前端配置:
第二臺
[root@localhost ~]# cd /var/www/html/
<html>
<body>
<h1>ni hao ?</h1>
<img src="http://192.168.91.3/a.jpg"/> ?#這里如果寫域名,需要修改hosts配置添加域名解析
</body>
</html>
實驗
第一臺
清空子配置文件:
添加圖片:?
第二臺機器:
添加httpd子配置文件:
測試
3.訪問盜取端地址,可以直接獲得被盜端圖片。
實現防盜鏈 :
server{
? ? ? ? listen 80;
? ? ? ? server_name www.lucky.com;
? ? ? ? root /data/html;
? ? ? ? location ~* \.(jpg|gif|swf)$ {
? ? ? ? root ?/data/html;
? ? ? ? valid_referers none blocked *.lucky.com lucky.com; ? ?
? ? ? ? if ( $invalid_referer ) {
? ? ? ? rewrite ^/ http://www.lucky.com/error.png;
? ? ? ? }
? ? }
}
實驗:
更改配置文件:
自定義返回圖片:?
更改配置文件:
三、反向代理
正向代理:代理的是客戶端去訪問服務端
反向代理:代理的是服務端
3.1定義
反向代理:reverse proxy,指的是代理外網用戶的請求到內部的指定的服務器,并將數據返回給用戶的一種方式,這是用的比較多的一種方式。
Nginx 除了可以在企業提供高性能的web服務之外,另外還可以將 nginx 本身不具備的請求通過某種預定義的協議轉發至其它服務器處理,不同的協議就是Nginx服務器與其他服務器進行通信的一種規范,主要在不同的場景使用以下模塊實現不同的功能。
3.2模塊
ngx_http_proxy_module: #將客戶端的請求以http協議轉發至指定服務器進行處理
?
ngx_http_upstream_module #用于定義為proxy_pass,fastcgi_pass,uwsgi_pass等指令引用的后端服務器分組 ? 負載均衡
?
ngx_stream_proxy_module:#將客戶端的請求以tcp協議轉發至指定服務器處理 ? 四層代理
?
ngx_http_fastcgi_module:#將客戶端對php的請求以fastcgi協議轉發至指定服務器助理
?
ngx_http_uwsgi_module: #將客戶端對Python的請求以uwsgi協議轉發至指定服務器處理
同構協議:代理服務器兩邊請求一樣
異構協議:代理服務器兩邊請求不一樣
主配置里面,PHP語言的程序模板已經寫好:
3.3實現http反向代理
3.3.1反向代理配置參數:
proxy_pass;?
#用來設置將客戶端請求轉發給的后端服務器的主機,可以是主機名(將轉發至后端服務做為主機頭首部)、IP
地址:端口的方式
#也可以代理到預先設置的主機群組,需要模塊 ngx_http_upstream_module 支持
?
示例:
10.0.0.8/web
?location /web {
? ?index index.html;
? ?proxy_pass http://10.0.0.18:8080;
#如果你訪問10.0.0.8/web 就相當于訪問10.0.0.18:8080
##8080后面無uri,即無 / 符號,需要將location后面url 附加到proxy_pass指定的url后面,此行為類似于root
?
?
重點:
如果location定義其uri時使用了正則表達式模式(包括~,~*,但不包括^~),則proxy_pass之后必須不能使用uri; 即不能有/ ,用戶請求時傳遞的uri將直接附加至后端服務器之后
server {
?...
?server_name HOSTNAME;
?location ~|~* /uri/ {
?proxy_pass http://host:port; ? # proxy_pass 后面的 url 不能加/
?}
?...
?}
?
proxy_hide_header field;
#用于 nginx 作為反向代理的時候,在返回給客戶端 http 響應時,隱藏后端服務器相應頭部的信息,可以設置
在http,server或location塊
?
#示例: 隱藏后端服務器ETag首部字段
?location /web {
? ?index index.html;
? ?proxy_pass http://10.0.0.18:8080/;?
? ?proxy_hide_header ETag;
?}
?
proxy_pass_header field;
#默認nginx在響應報文中不傳遞后端服務器的首部字段Date, Server, X-Pad, X-Accel等參數,如果
要傳遞的話則要使用 proxy_pass_header field 聲明將后端服務器返回的值傳遞給客戶端
#field 首部字段大小不敏感
?
#示例:透傳后端服務器的 Server 和 Date 首部給客戶端,同時不再響應報中顯示前端服務器的Server字段
proxy_pass_header Server;
proxy_pass_header Date;
?
?
proxy_pass_request_body on | off;?
#是否向后端服務器發送HTTP實體部分,可以設置在http,server或location塊,默認即為開啟
?
?
proxy_pass_request_headers on | off;?
#是否將客戶端的請求頭部轉發給后端服務器,可以設置在http,server或location塊,默認即為開啟
3.4實戰:反向代理單臺web服務器:
客戶端:192.168.91.5,服務器:192.168.91.4;代理服務器:192.168.91.3
代理服務器配置文件:
客戶端開啟httpd服務:
客戶端訪問代理服務器:
3.5http反向代理負載均衡:
3.5.1概述
?Nginx 可以將客戶端的請求轉發至單臺后端服務器,但是無法轉發至特定的一組的服務器,而且不能對后端服務器提供相應的服務器狀態監測,Nginx 可以基于 ngx_http_upstream_module 模塊提供服務器分組轉發、權重分配、狀態監測、調度算法等高級功能。
配置方式
server address [parameters];
#配置一個后端web服務器,配置在 upstream 內,至少要有一個 server 服務器配置。
?
#server 支持的 parameters 如下:
weight=number ? #設置權重,默認為1,實現類似于LVS中的WRR,WLC等
?
max_conns=number ?#給當前后端server設置最大活動鏈接數,默認為0表示沒有限制
?
max_fails=number ?#后端服務器的下線條件,當客戶端訪問時,對本次調度選中的后端服務器連續進行檢測多少次,如果都失敗就標記為不可用,默認為1次,當客戶端訪問時,才會利用TCP觸發對探測后端服務器健康性檢查,而非周期性的探測
?
fail_timeout=time #后端服務器的上線條件,對已經檢測到處于不可用的后端服務器,每隔此時間間隔再次進行檢測是否恢復可用,如果發現可用,則將后端服務器參與調度,默認為10秒
?
backup ?#設置為備份服務器,當所有后端服務器不可用時,才會啟用此備用服務器 sorry server ? 自己不能轉自己
?
down ? ?#標記為 down 狀態
?
resolve #當 server 定義的是主機名的時候,當A記錄發生變化會自動應用新IP而不用重啟Nginx
配置格式:
http {
? ? upstream web {
? ? ? ? server 192.168.91.3 weight=5;
? ? ? ? server 192.168.91.4;
? ? ? ? server 192.168.91.5;
?
? ? ? ? least_conn;
? ? ? ? ip_hash;
? ? ? ? keepalive 32;
? ? ? ? fair;
? ? }
}
?
server {
? ? listen 80;
? ? server_name www.lucky.com;
? ? proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
? ? root /data/html;
? ? location / {
? ? proxy_pass ?http://web/
? ? }
}
上面的配置中,upstream塊定義了后端服務器的列表和負載均衡算法。server塊定義了反向代理服務器的監聽端口和域名,以及請求轉發的配置。具體說明如下:
upstream塊:定義了一個名為web的負載均衡服務器組,其中包含了三個后端服務器,分別是192.168.91.3、192.168.91.4、192.168.91.5。?
weight=5表示將第一個后端服務器的權重設置為5,即分配更多的請求給它。ip_hash表示使用IP哈希算法進行負載均衡。keepalive 32表示使用長連接并保持32個連接。?
server塊:定義了一個監聽80端口的虛擬主機,它的域名是www.pc.com。location /表示將所有請求轉發給upstream塊中定義的服務器組web。proxy_set_header指令可以設置請求頭,以便后端服務器能夠獲取客戶端的真實IP地址等信息。
由于使用了least_conn;算法,Nginx會動態地將請求發送到當前連接數最少的后端服務器上,以達到負載均衡的目的。
upstream塊中使用了ip_hash算法,表示會根據客戶端的IP地址,將該客戶端的所有請求都發送到同一個后端服務器上。
由于使用了fair算法,請求會被發送到響應時間最短的服務器上,從而實現負載均衡。
3.5.2調度算法
1. 輪詢? 一人一次
2. 加權輪詢
3. ip hash
4. url hash
5. cookie hash
6.最少連接數
7.fair 根據響應時間
3.6stream 服務模塊:
用的四層,只能控制tcp、udp(實現反向代理功能,包括TCP協議代理)
配置文件: vim /etc/redis.conf
3.7四層代理和七層代理的區別:
4層是指傳輸層的 TCP/UDP 協議
7層是指應用層的 HTTP 協議
代理原理:
? ? ?4層代理:使用 NAT(Network Address Translation)技術,即網絡地址轉換。即請求進來的時候,nginx 只修改數據包里面的目標IP、源IP、端口,然后就直接把數據包發給目標服務器(即nginx不知道請求的具體內容),目標服務器處理完成后,發給 nginx,nginx 數據包再做一次類似的修改,就返回給請求的客戶端了。
? ? ?7層代理:nginx 讀取并解析 Http 請求內容,然后將具體內容(請求行、請求頭、空行、請求數據)轉發到相應的服務器,轉發的過程是:建立和目標機器的連接,然后轉發請求,收到響應數據再轉發給請求客戶端。