基於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