Nginx域名訪問的白名單配置 - 運維總結

 

在平常運維工做中,會碰到這樣的需求:設置網站訪問只對某些ip開放,其餘ip的客戶端都不能訪問。能夠經過下面四種方法來達到這種效果:
1)針對nginx域名配置所啓用的端口(好比80端口)在iptables裏作白名單,好比只容許100.110.15.1六、100.110.15.1七、100.110.15.18訪問.可是這樣就把nginx的全部80端口的域名訪問都作了限制,範圍比較大!php

[root@china ~]# vim /etc/sysconfig/iptables
......
-A INPUT -s 100.110.15.16 -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A INPUT -s 100.110.15.17 -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A INPUT -s 100.110.15.18 -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT

2)若是隻是針對nginx下的某一個域名進行訪問的白名單限制,那麼能夠在nginx的配置文件裏進行設置,利用$remote_addr參數進行訪問的分發限制,以下:html

[root@china vhosts]# cat testwww.wangshibo.com.conf 
server {
        listen       80;
        server_name  testwww.wangshibo.com;
        root /var/www/vhosts/testwww.wangshibo.com/httpdocs/main;


        access_log  /var/www/vhosts/testwww.wangshibo.com/logs/access.log  main;
        error_log  /var/www/vhosts/testwww.wangshibo.com/logs/error.log;


        ##白名單設置,只容許下面三個來源ip的客戶端以及本地能訪問該站。主要是下面這三行
        if ($remote_addr !~ ^(100.110.15.16|100.110.15.17|100.110.15.18|127.0.0.1)) {
         rewrite ^.*$ /maintence.php last;
        }

        location / {
            try_files $uri $uri/ @router;
            index  index.php;
        }
    

        error_page   500 502 503 504  /50x.html;

        location @router {
            rewrite ^.*$ /index.php last;
        }


        location ~ \.php$ {
            fastcgi_pass   127.0.0.1:9001;
            fastcgi_read_timeout 30;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
            #include        fastcgi_params;
            include        fastcgi.conf;
        }

    } 


錯誤頁面內容設置:
[root@china vhosts]# cat /var/www/vhosts/testwww.wangshibo.com/main/maintence.html 
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
</head>
<body>
網站臨時維護中,請稍後訪問...
</body>
</html>

3)也可使用$http_x_forwarded_for參數進行訪問的分發限制,以下:nginx

server {
        listen       80;
        server_name  testwww.wangshibo.com;
        root /var/www/vhosts/testwww.wangshibo.com/httpdocs/main;


        access_log  /var/www/vhosts/testwww.wangshibo.com/logs/access.log  main;
        error_log  /var/www/vhosts/testwww.wangshibo.com/logs/error.log;


  ##白名單設置,只容許下面三個來源ip的客戶端以及本地能訪問該站。
       if ($http_x_forwarded_for !~ ^(100.110.15.16|100.110.15.17|100.110.15.18|127.0.0.1)) {
           rewrite ^.*$  /maintence.php last;
        }
        
        
        location / {
            try_files $uri $uri/ @router;
            index  index.php;
        }
    

        error_page   500 502 503 504  /50x.html;

        location @router {
            rewrite ^.*$ /index.php last;
        }


        location ~ \.php$ {
            fastcgi_pass   127.0.0.1:9001;
            fastcgi_read_timeout 30;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
            #include        fastcgi_params;
            include        fastcgi.conf;
        }

    } 

4)還能夠利用nginx的allow、deny參數進行訪問限制web

[root@china vhosts]# cat testwww.wangshibo.com.conf 
server {
        listen       80;
        server_name  testwww.wangshibo.com;
        root /var/www/vhosts/testwww.wangshibo.com/httpdocs/main;


        access_log  /var/www/vhosts/testwww.wangshibo.com/logs/access.log  main;
        error_log  /var/www/vhosts/testwww.wangshibo.com/logs/error.log;

        ##白名單設置,只容許下面三個來源ip的客戶端以及本地能訪問該站。
        allow 100.110.15.16;
        allow 100.110.15.17;
        allow 100.110.15.18;
        allow 127.0.0.1;
        deny all;

        location / {
            try_files $uri $uri/ @router;
            index  index.php;
        }
    

        error_page   500 502 503 504  /50x.html;

        location @router {
            rewrite ^.*$ /index.php last;
        }


        location ~ \.php$ {
            fastcgi_pass   127.0.0.1:9001;
            fastcgi_read_timeout 30;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
            #include        fastcgi_params;
            include        fastcgi.conf;
        }

    } 

---------------------------------nginx中remote_addr和x_forwarded_for參數使用說明---------------------------------正則表達式

作網站時常常會用到remote_addr和x_forwarded_for這兩個頭信息來獲取客戶端的IP,然而當有反向代理或者CDN的狀況下,這兩個值就不夠準確了,須要調整一些配置。

1)什麼是remote_addr
remote_addr表明客戶端的IP,但它的值不是由客戶端提供的,而是服務端根據客戶端的ip指定的,當你的瀏覽器訪問某個網站時,假設中間沒有任何代理,那麼網站的
web服務器(Nginx,Apache等)就會把remote_addr設爲你的機器IP,若是你用了某個代理,那麼你的瀏覽器會先訪問這個代理,而後再由這個代理轉發到網站,這樣web
服務器就會把remote_addr設爲這臺代理機器的IP。

2)什麼是x_forwarded_for
正如上面所述,當你使用了代理時,web服務器就不知道你的真實IP了,爲了不這個狀況,代理服務器一般會增長一個叫作x_forwarded_for的頭信息,把鏈接它的客戶
端IP(即你的上網機器IP)加到這個頭信息裏,這樣就能保證網站的web服務器能獲取到真實IP


-------------------使用HAProxy作反向代理----------------------
一般網站爲了支撐更大的訪問量,會增長不少web服務器,並在這些服務器前面增長一個反向代理(如HAProxy),它能夠把負載均勻的分佈到這些機器上。你的瀏覽器訪
問的首先是這臺反向代理,它再把你的請求轉發到後面的web服務器,這就使得web服務器會把remote_addr設爲這臺反向代理的IP,爲了能讓你的程序獲取到真實的客戶端
IP,你須要給HAProxy增長如下配置:

option forwardfor
它的做用就像上面說的,增長一個x_forwarded_for的頭信息,把你上網機器的ip添加進去



------------------使用Nginx的realip模塊--------------------
當Nginx處在HAProxy後面時,就會把remote_addr設爲HAProxy的IP,這個值實際上是毫無心義的,你能夠經過nginx的realip模塊,讓它使用x_forwarded_for裏的值。使用這
個模塊須要從新編譯Nginx,增長--with-http_realip_module參數

set_real_ip_from   10.1.10.0/24;
real_ip_header     X-Forwarded-For;
上面的配置就是把從10.1.10這一網段過來的請求所有使用X-Forwarded-For裏的頭信息做爲remote_addr


------------------將Nginx架在HAProxy前面作HTTPS代理---------------
網站爲了安全考慮一般會使用https鏈接來傳輸敏感信息,https使用了ssl加密,HAProxy無法直接解析,因此要在HAProxy前面先架臺Nginx解密,再轉發到HAProxy作負載均
衡。這樣在Web服務器前面就存在了兩個代理,爲了能讓它獲取到真實的客戶端IP,須要作如下配置。

首先要在Nginx的代理規則裏設定:
proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
這樣會讓Nginx的https代理增長x_forwarded_for頭信息,保存客戶的真實IP。

其次修改HAProxy的配置:
option     forwardfor except 10.1.10.0/24
這個配置和以前設定的差很少,只是多了個內網的IP段,表示若是HAProxy收到的請求是由內網傳過來的話(https代理機器),就不會設定x_forwarded_for的值,保證後面的
web服務器拿到的就是前面https代理傳過來的。



-----------------爲何PHP裏的HTTP_X_FORWARDED_FOR和Nginx的不同------------------
當你的網站使用了CDN後,用戶會先訪問CDN,若是CDN沒有緩存,則回源站(即你的反向代理)取數據。CDN在回源站時,會先添加x_forwarded_for頭信息,保存用戶的真實IP,
而你的反向代理也會設定這個值,不過它不會覆蓋,而是把CDN服務器的IP(即當前remote_addr)添加到x_forwarded_for的後面,這樣x_forwarded_for裏就會存在兩個值。
Nginx會使用這些值裏的第一個,即客戶的真實IP,而PHP則會使用第二個,即CDN的地址。爲了能讓PHP也使用第一個值,你須要添加如下fastcgi的配置。

fastcgi_param HTTP_X_FORWARDED_FOR $http_x_forwarded_for;
它會把nginx使用的值(即第一個IP)傳給PHP,這樣PHP拿到的x_forwarded_for裏其實就只有一個值了,也就不會用第二個CDN的IP了。

忽略x_forwarded_for

其實,當你使用了Nginx的realip模塊後,就已經保證了remote_addr裏設定的就是客戶端的真實IP,再看下這個配置

set_real_ip_from   10.1.10.0/24;
real_ip_header     X-Forwarded-For;
它就是把x_forwarded_for設爲remote_addr,而nginx裏的x_forwarded_for取的就是其中第一個IP。

使用這些設置就能保證你的remote_addr裏設定的一直都是客戶端的真實IP,而x_forwarded_for則能夠忽略了:)

---------------------------------下面簡單說明下nginx location匹配規則-------------------------------------------vim

location匹配命令
~   表示執行一個正則匹配,區分大小寫
~* 表示執行一個正則匹配,不區分大小寫
^~ 表示普通字符匹配,若是該選項匹配,只匹配該選項,不匹配別的選項,通常用來匹配目錄
=    進行普通字符精確匹配
@   定義一個命名的 location,使用在內部定向時,例如 error_page, try_files

=前綴的指令嚴格匹配這個查詢。若是找到,中止搜索。
全部剩下的常規字符串,最長的匹配。若是這個匹配使用^〜前綴,搜索中止。
正則表達式,在配置文件中定義的順序。
若是第3條規則產生匹配的話,結果被使用。不然,如同從第2條規則被使用。

location 匹配的優先級(與location在配置文件中的順序無關)
= 精確匹配會第一個被處理。若是發現精確匹配,nginx中止搜索其餘匹配。
普通字符匹配,正則表達式規則和長的塊規則將被優先和查詢匹配,也就是說若是該項匹配還需去看有沒有正則表達式匹配和更長的匹配。
^~ 則只匹配該規則,nginx中止搜索其餘匹配,不然nginx會繼續處理其餘location指令。
最後匹配理帶有"~"和"~*"的指令,若是找到相應的匹配,則nginx中止搜索其餘匹配;當沒有正則表達式或者沒有正則表達式被匹配的狀況下,那麼匹配程度最高的逐字匹配指令會被使用。 
location = / {                     # 只匹配"/".
[ configuration A ] 
}

location / {                        # 匹配任何請求,由於全部請求都是以"/"開始,可是更長字符匹配或者正則表達式匹配會優先匹配
[ configuration B ] 
}

location ^~ /images/ {           # 匹配任何以 /images/ 開始的請求,並中止匹配 其它location
[ configuration C ] 
}

location ~* \.(gif|jpg|jpeg)$ {         # 匹配以 gif, jpg, or jpeg結尾的請求. 可是全部 /images/ 目錄的請求將由 [Configuration C]處理. 
[ configuration D ] 
}
相關文章
相關標籤/搜索