Nginx訪問控制_IP訪問控制(http_access_module)原理、侷限性、解決方法講解

OldBoy~發表於2018-01-09

基於IP的訪問控制,基於Nginx的http_access_module模組,是Nginx本身內建的模組,不需要安裝的時候配置。也就是允許哪些IP訪問,不允許哪些IP訪問

server {
  listen       80;
  server_name example.com;
  access_log logs/access.log main;
  location / {
       deny 192.168.1.1;
       allow 192.168.1.0/24;
       allow 10.1.1.0/16;
       allow 2001:0db8::/32;
       deny all;
       #從上到下的順序,類似iptables。匹配到了便跳出。如上的例子先禁止了192.16.1.1,接下來允許了3個網段,其中包含了一個ipv6,最後未匹配的IP全部禁止訪問.被deny的將返回403狀態碼。
  }
  location ~ ^/phpmyadmin/ {
      allow 192.168.1.0/24;
      deny all;
      #只允許區域網訪問
  }
   location /project {  
       allow   220.178.25.22;  
       allow   172.2.2.0/24;  
       allow   192.2.2.0/24;  
       deny    all;  
       proxy_pass http://172.2.2.20:8080/project/;  
       proxy_set_header   Host    $host:$server_port;  
       proxy_set_header   X-Real-IP   $remote_addr;   
       proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;  
       client_max_body_size    10m;  
   }  
    #以上配置的作用是允許IP為220.178.25.22,以及172和192網段的機器可以訪問這個location地址,其他IP的客戶端訪問均是403。其中,24是指子網掩碼為255.255.255.0。
}

Nginx基於access_module有侷限性

原理:基於客戶端的IP,但是對於Nginx來說,它不會管你哪個是真正的客戶端,如果我們的訪問不是客戶端與服務端直接連線,而是通過了一層代理,比如它的代理可以負載均衡、CDN的這種代理實現,也就是我們的訪問不是客戶端直接訪問的服務端,而是通過其他的中介軟體訪問服務端,這時候會出現一個問題,因為Nginx的access_module它是基於remote_addr這個變數來識別客戶端的IP的,那麼如果一個ip通過中介軟體訪問服務端,那麼Nginx認為訪問的ip就是中介軟體的IP,那麼我們在基於IP做限制的時候,那麼其實是沒有作用的。所以這樣的話,準確性是不高的,所以就是利用nginx的access_module有侷限性。
解決方法:

①:採用別的http頭資訊訪問控制,如HTTP_X_FORWARDED_FOR。

但是http_x_forwarded_for進行訪問控制會存在問題,因為是一個協議要求的,並不是所有的cdn和代理廠商它會按照要求來做,甚至x_forwarded_for存在被修改的可能,因為只是一個頭資訊,所以最終還是不真實。

http_x_forwardded_for也是Nginx的http頭變數的一個常用的變數,它和remote_addr是有區別的。不同的是,x_forwarded_for是http協議中規定頭中要攜帶的,所以在客戶端訪問中介軟體,再訪問服務端的時候,那麼服務端通過Nginx會記錄真實IP和中介軟體的IP。
格式:http_x_forwarded_for = 客戶端ip,第一臺代理ip,第二臺代理ip,第N臺代理ip....,所以http_x_forwarded_for是由一連串以逗號分隔的ip組成的。
②:結合geo模組
③:通過HTTP自定義變數傳遞
因為nginx有自己的變數,我們可以在http頭資訊定義一個我們規定的http變數在所有上一級的裝置手動把remote_addr的ip一級一級的攜帶過去,既能避免x_forwarded_for被修改,也能讀到客戶端的真實ip

記得修改完配置一定要檢測Nginx配置是否正確,正確後再重新軟載入配置檔案

[root@~]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@~]# /usr/local/nginx/sbin/nginx -s reload

 

相關文章