Nginx配置IP白名单

环境交代

Nginx配置IP白名单是非常基础的工作,这次试验就是配置某网页可以正常被部分IP访问,而其他网页访问将是403。目标网页地址是http://xxdtq.lechange.com/test/test.html,内容如下:
akb48

本机的外网IP地址是115.205.2.28,如图:
akb48

首先先nginx.conf里的日志配置格式如下:

1
2
3
log_format  access '$http_x_forwarded_for - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $remote_addr $request_time $upstream_response_time $http_host';

Nginx的转发文件default.conf如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
server {
listen 80;
server_name xxdtq.lechange.com; #如果浏览器输入的是xxdtq.lechange.com,那么就跳转到82端口
location / {
proxy_pass http://localhost:82;
}
}

server {
listen 80;
server_name xhssf.lechange.com; #如果浏览器输入的是xhssf.lechange.com,那么就跳转到82端口
location / {
proxy_pass http://localhost:83;
}
}

配置步骤

现在配置xxdtq.conf文件内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
	server
{
listen 82 default; #82端口
server_name xxdtq.lechange.com;
root /mnt/xiuxiudetiequan/; #根目录是/mnet/xiuxiudetiequan/
index index.html index.htm index.php;

add_header Set-Cookie "HttpOnly";
add_header Set-Cookie "Secure";
add_header X-Frame-Options "SAMEORIGIN";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

location = /test/test.html { #如果remote_addr是125.205.2.28来访问/test/test.html,那么就返回403
if ($remote_addr = 115.205.2.28) {
return 403;
}
}

access_log /var/log/nginx/xxdtq/access.log access;
error_log /var/log/nginx/xxdtq/error.log error;
}

执行了nginx -s reload后,刷新一下界面,却发现页面没变,并不是预期中的403,打开nginx的日志一看,发现获取到的$remote_addr127.0.0.1!如下:
akb48

为什么是127.0.0.1?因为我们这个nginx做了一个80到82端口的转发呀,所以到80的地址是真实的外界IP,而80转发到82就是本机IP了。那这样的情况怎么办?就需要在default.conf里添加一句proxy_set_header x-forwarded-for $remote_addr;,如下:

1
2
3
4
5
6
7
8
server {
listen 80;
server_name xxdtq.lechange.com;
location / {
proxy_pass http://localhost:82;
proxy_set_header x-forwarded-for $remote_addr;
}
}

重启一波nginx,发现http_x_forwarded_for正是远程访问的IP地址115.205.2.28,于是将xxdtq.conf判断IP改成如下内容:

1
2
3
4
5
location = /test/test.html {
if ($http_x_forwarded_for = 115.205.2.28) { #改用http_x_forwarded_for
return 403;
}
}

重启nginx之后,果然页面是403,如图:
akb48

然后用其他的IP地址,比如用手机连接4G去打开http://xxdtq.lechange.com/test/test.html ,发现是正常读取的,试验成功!
akb48

如果是要整个/test/目录都不让访问的话,就要改成如下内容:

1
2
3
4
5
location ^~ /test/ {
if ($http_x_forwarded_for = 115.205.2.28) { # =是精确匹配
return 403;
}
}

如果要配置多个IP地址,就要改成如下内容:

1
2
3
4
5
location ~ ^/shopadmin {
if ($remote_addr ~* "第一个IP|第二个IP|第三个IP") { #这里改成~*
return 403;
}
}

elk里提取http_x_forwarded_for

nginx日志中的http_x_forwarded_for字段会有多个IP。使用自定义的模板,grok常用表达式的IPORHOST匹配http_x_forwarded_for该字段,获取的IP值是最后一个,如何取第一个IP值?

答案是:

1
2
3
4
mutate {
split => ["http_x_forwarded_for",","]
add_field => ["real_remote_addr","%{http_x_forwarded_for[0]}"]
}

IPORHOST这些变量匹配不到所有IP,只能通过自定义正则来匹配到所有IP;再通过以上方法截取第一个IP值。正则表达式写法是:[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\,\s]*

参考资料

http://seanlook.com/2015/05/17/nginx-location-rewrite/
https://zhuanlan.zhihu.com/p/21354318
http://blog.pengqi.me/2013/04/20/remote-addr-and-x-forwarded-for/
http://gong1208.iteye.com/blog/1559835
https://my.oschina.net/moooofly/blog/295853

-------------This article is over!Thanks for reading!-------------
感谢您请我喝咖啡!(o´ω`o)
0%