Nginx之反向代理配置(一)

  前文咱們聊了下Nginx做爲web服務器配置https、日誌模塊的經常使用配置、rewrite模塊重寫用戶請求的url,回顧請參考http://www.javashuo.com/article/p-opoqpxfm-cv.html;今天來聊一聊Nginx是怎麼反向代理,怎麼防盜鏈;前文的最後咱們提到了防盜鏈,到底什麼是防盜鏈呢?在咱們平時上網相信不少人都遇到過這樣的狀況,咱們打開一個網頁,在裏面能夠看到不少裂圖,看不到圖片,或者看到此圖片僅某某網站網友交流使用之類的,這就是防盜鏈;咱們知道在一個網頁裏面,裏面的資源不必定都是來自一個服務器的,好比圖片極可能來自圖片服務器,js、css極可能來自其餘靜態資源服務器上;因此稍微懂點的人就知道如何將別人網站上的圖片、js文件呀連接到本身的網站使用,這種行爲就叫盜用別人家的資源,簡稱盜鏈;這裏就不過多闡述了;咱們來講說nginx的referer模塊吧。css

  1、ngx_http_referer_module:此模塊用於阻止對「Referer」頭字段中包含無效值的請求的站點訪問;html

  一般一次http事務就是客戶端請求服務端,服務端響應客戶端的一個流程;客戶端請求服務端,會在請求頭部添加一些信息,好比用什麼方法請求服務端的資源呀,資源的路徑是什麼,用的http協議版本是多少,請求的host主機上什麼等等;其中若是客戶端是直接從瀏覽器上介入域名直接訪問web服務器,其頭部是沒有referer這個信息的;referer是什麼?referer是記錄客戶端從哪裏來訪問咱們客戶端的,若是客戶端是經過某個網站點擊訪問到咱們的服務器時,它發過來的請求頭部就有對應網站的域名;防盜鏈就是利用referer這個頭部的信息來作控制的;linux

  一、valid_referers none | blocked | server_names | string ...;定義合法referer合法值;這裏解釋下,none表示請求頭部沒有referer字段,一般狀況下沒有referer字段都是從瀏覽器(web客戶端)介入域名訪問的;blocked表示請求頭部有referer字段,可是沒有值,像這種請求咱們是沒法判斷客戶端是從哪裏訪問咱們服務器的,一般狀況咱們把這類請求時容許訪問的;server_name表示請求頭部有referer字段和信息,其值就是對方主機名;咱們在定義一個合法的referer時,是能夠用通配或正則去匹配server_name;nginx

  示例:web

valid_referers none blocked server_names
               *.example.com example.* www.example.org/galleries/
               ~\.google\.;

  提示:以上配置表示合法的referer有 ,請求報文裏沒有referer字段的請求,有referer字段可是沒有值的,以任何內容開頭結尾是.example.com的主機名或者是以example開頭的主機,或者referer是www.example.org/galleries/或者是包含google的都是合法的,意思是客戶端請求報文的referer信息知足咱們定義的合法信息,或者說可以被咱們定義的合法referer匹配到,咱們就說該用戶是一個合法的請求,理所固然的是應該容許被訪問的;固然咱們定義了合法referer,若是客戶端請求報文裏的referer信息不配咱們定義的合法referer匹配,咱們就說這裏客戶端的referer是非法的,是不被容許的,理所固然的就應該作其餘處理;這個是ngxin裏內部的機制,不被合法referer所匹配的referer都是非法的referer,一般是用$invalid_referer保留這些不合法referer;或者咱們這樣理解,不被合法referer所匹配的請求報文就會被$invalid_referer所匹配;有了這種機制咱們就能夠明肯定義那些請求時合法的,相對的那些請求是不合法的,對於不合法的咱們能夠這麼處理;以下算法

   提示:以上配置表示若是客戶端請求報文的referer信息不是.ilinux.com結尾或者不是以www.ilinux.開頭 或者 不是www.ilinux.io 或者不包含.baidu.或者.google. 咱們都響應該客戶端請求響應碼爲403;後端

  2、ngx_http_proxy_module:此模塊容許將請求傳遞到另外一個服務器。瀏覽器

  一、proxy_pass URL;該指令主要做用是用來設置被代理服務器地址的,能夠說主機名稱,IP地址加端口的形式;其中URL表示被代理服務器的地址,包含協議、主機名或IP加端口、URI等。傳輸協議一般是「http」或者"https";若是咱們被代理的是一個本地unix-domain套接字時,也支持以http://或https://加unix套接字路徑的形式;若是咱們代理的是一組服務器時,咱們能夠用upstream指令把該組服務器同一歸併爲一個名稱的組服務器組,固然這是咱們後面要聊的nginx做爲負載均衡的配置;這裏特別要說明的是URL中是否包含URI,什麼意思呢,就是URL不包含URI的意思就是 被代理的URL沒有URI,就只有協議IP地址或域名或主機名,這種就叫不帶URI;帶URI就表示除了協議主機名或域名或IP地址外,後面還有RUI;對於這兩種狀況Nginx處理邏輯上不同的,若是RUL不包含URI 那麼nginx服務器不會改變源地址的URI;若是URL包含URI,nginx服務器將會使用新的URI替換原來的URI;緩存

  示例:bash

   提示:以上配置就是咱們所的URL不包含URI的狀況,用戶請求www.test.com/en/docs/將會被該location匹配到,而後將訪問www.test.com/en/docs/將會被代理到http://nginx.org/en/docs/;咱們能夠理解爲被代理的URL不包含URI時,Nginx服務器會把用戶請求的URI看成被代理服務器的URI;因此以上配置就表示,用戶訪問www.test.com/en/docs/將被代理至http://nginx.org/en/docs/

  提示:在作以上實驗時,須要在Windows上作好解析www.test.com;Windows上須要在C:\Windows\System32\drivers\etc\hosts文件中添加一條解析記錄,語法同Linux裏的hosts同樣192.168.0.30 www.ilinux.io www.test.com;

   提示:以上配置就是URL包含URI的狀況,這種狀況Nginx服務器會把用戶請求的URI替換成被代理的URI;以上面的配置示例,若是用戶請求www.test.com/test/那麼這個請求到了nginx服務器時,nginx會把用戶原有的URI/test/替換成/en/docs/,因此用戶請求www.test.com/test/就會被代理至http://nginx.org/en/docs/;

  提示:經過上面的演示,咱們能夠總結爲,若是咱們不想改變源請求的URI,那麼咱們在後端代理時就不帶URI,若是咱們想更改源請求URI,那麼咱們在後端代理時,就帶上URI便可

  理解了上面咱們所的URL包含或不包含URI,咱們就不難理解下面的例子

  示例:proxy_pass URL末尾是否帶「/」問題

   提示:以上配置和咱們以前的第一個示例就只多了一個「/」;多一個「/」在咱們看來是沒關係,但它對nginx來講,意思卻變了,就以咱們上面說的,這種就是URL包含URI的狀況,nginx會把後面的「/」認爲是URI,不是認爲,它原本就是一個URI;當客戶端請求www.test.com/en/docs/時,nginx會把該請求代理至http://nginx.org/;固然這樣處理後的結果確定和咱們以前的結果是徹底不同的,http://nginx.org/就表示請求nginx.org的主頁;

  提示:和第一個示例同樣的URL,對於proxy_pass URL後面沒有"/"和有「/」被代理響應的結果是不同的;

  除了上面URL包含或不包含URI問題須要咱們特別注意外,咱們還要注意,若是location定義URI時使用了正則,或在if語句或在limit_execept中使用了proxy_pass指令,則proxy_pass 以後不能使用URI;用戶請求時傳遞的URI將直接附加代理到的服務器以後;意思就是URL包含URI的狀況不能在location 使用了正則匹配URL,或者URL包含URI的狀況不容許用在if語句中  或limit_except中

  示例:

   提示:這種配置咱們在語法檢查的時候就通不過,要想被經過,咱們只須要把proxy_pass指令後面的URI去掉便可

   提示:總結一點就是location中使用了正則匹配 URL時,後面代理是不能有URI的,不然語法錯誤;

   二、proxy_set_header field value;設定發日後端主機的請求報文的請求首部的值;可用在http,server,location配置段中

proxy_set_header X-Real-IP  $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

  提示:以上配置表示在用戶請求經過代理髮送給後端主機時,在其請求頭部加上X-Real-IP這個字段,而且這個字段的值是$remote_addr(客戶端IP地址)和X-Forwarded-For字段,其值爲$proxy_add_x_forwarded_for;$proxy_add_x_forwarded_for 這個變量是也是記錄IP地址的,不一樣的是,這個變量它記錄了客戶端IP和代理服務端ip,兩個IP分別用逗號隔開,若是沒有代理服務器的場景,這個變量的意義同$remote_addr是同樣的,都是記錄客戶端客戶端IP

  三、proxy_cache_path:定義可用於proxy功能的緩存,此指令只可配置在http配置段;

  語法:

    proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];

    path:表示設置緩存數據存放路徑,該路徑必須事先存在;

    levels;表示設置存放緩存數據的目錄級別,這個和前面說的nginx緩存目錄同樣。levels=1:2表示兩級目錄,且一級目錄是一個字符哈希目錄,二級目錄是兩個字符的哈希目錄,目錄名稱是基於URL哈希算法獲取到的;

    keys_zone=name:size 表示設置緩存索引在內存區域的名稱和大小;

    inactive=time設置非活動緩存時間,在指定的時間內若是該緩存項沒有被命中,nginx就會強制把該緩存從磁盤上刪除,若是下次有人訪問時在緩存,依次循環;默認10分鐘;

    max_size=size:設置磁盤中緩存數據的大小限制,當緩存數據超過咱們設定的大小時,就是用LRU算法來刪除緩存;

    loader_files=number:設置緩存索引重建進程每次加載的數據元素的數量上限;

    loader_sleep=time:設置緩存索引重建進程在一次遍歷結束、下次遍歷開始之間的暫停時長,默認是50ms

    loader_threshold=time:設置遍歷一次磁盤緩存源數據的時間上限,默認設置爲200ms

  一般狀況下咱們不須要設置這麼多選項,只須要把前三個選項設置好就好了,沒有特殊的要求後面的選項咱們用默認值就能夠

  示例:

   提示:以上配置表示定義代理緩存路徑是/cache/proxy/nginx 目錄級別是1:2:1  緩存索引重建進程內存區域名稱爲proxy_cache,大小爲10M 對於磁盤上的/cache/proxy/nginx/目錄最大緩存空間爲2g;這樣設置後,咱們就能夠在各個server或location中來調用此緩存定義

  四、proxy_cache zone | off;指明要調用的緩存,或關閉緩存機制;此指令可用於http,server,location配置段中;

  示例

   提示:這樣去調用緩存空間進行緩存是不可以緩存的,由於咱們調用緩存空間是有條件的,好比咱們要對那些請求方法的請求進行緩存?對不一樣響應碼的資源緩存多久?是否在後端服務器出現錯誤時,咱們繼續使用緩存來響應?因此咱們如今雖然配置了調用緩存空間,可是咱們服務器仍是不知道怎麼去緩存客戶訪問的內容;因此它乾脆就不給緩存;

  示例:咱們只調用了緩存空間,沒有配置其餘配置,用戶訪問的數據是否可以緩存下來呢?

  提示:能夠看到咱們只配置緩存空間而後調用是不行的,咱們還須要指定緩存的key是什麼 ,對客戶端使用的那些方法進行緩存,對不一樣的響應碼的資源緩存多久,這是調用緩存空間的幾個必要的配置,咱們須要加上才行;

  五、proxy_cache_key:定義緩存key,默認是$scheme$proxy_host$request_uri,它這個默認就是緩存的key是協議加代理主機地址或主機名或FQDN和用戶請求的uri看成緩存的KEY;也就是說服務端怎麼去找緩存的方式,對應key的定義;

  六、proxy_cache_methods METHODS:定義緩存用戶的請求方式,也就是說那些請求方法的資源咱們要進行緩存,默認是GET HEAD;

  七、proxy_cache_valid code:定義不一樣的響應碼的資源緩存時長;

  八、proxy_cache_use_stale error |timeout|……:定義後端服務器基於那種狀態使用緩存,默認是不基於後端服務器狀態使用緩存;好比後端服務器發生錯誤,是否用緩存中的內容響應客戶端?若是咱們定義 proxy_cache_use_stale http 403就表示後端服務器若是響應代理服務器403,咱們代理服務器就是用以前的緩存,響應客戶端;

  示例:

   提示:以上配置表示使用proxy_cache緩存空間,緩存key是用戶請求的uri進行緩存,對用戶使用GET 和HEAD方法請求的資源進行緩存,對響應碼是200 302的資源緩存15分鐘,對響應碼是404的資源緩存1分鐘,後端服務器出現500 或502的錯誤,代理服務器使用之前的緩存響應客戶端;

   提示:可看到瀏覽器請求了兩個uri,在對應的緩存目錄裏就存在兩個緩存項;這裏面每個緩存項就是對應一個用戶請求過多URI;一般狀況咱們啓用了Nginx代理緩存功能時,用戶第一次訪問就會很慢,可是隻要把數據緩存下來後,後續的用戶在訪問相同的URI時,這個速度就會有明顯的提高;

   總結對於nginx的緩存,咱們首先在http配置段定義一個緩存空間,而後在各server或location中調用咱們定義的緩存空間,並明確說明各類響應碼的資源緩存多長時間,對於proxy_cache_key 和 proxy_cache_methods是能夠不指定的,不指定就表明使用默認值,從上面的配置咱們其實就只定義響應碼是多少的資源緩存多久,其餘的按照默認來,它也是能夠進行緩存的;

相關文章
相關標籤/搜索