9

在 NGINX 中根据用户真实 IP 进行限制 - 东风微鸣

 1 year ago
source link: https://www.cnblogs.com/east4ming/p/17048827.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

在 NGINX 中根据用户真实 IP 进行限制

需要根据用户的真实 IP 进行限制, 但是 NGINX 前边还有个 F5, 导致 deny 指令不生效.

阻止用户的真实 IP 不是 192.168.14.*192.168.15.* 的访问请求.

最简单的实现如下:

📓 前置条件:

需要 nginx 前边的 load balancer 设备(如 F5)开启 X-Forwarded-For 支持.

proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;

if ($proxy_add_x_forwarded_for !~ "192\.168\.1[45]")  {
    return 403;
}      

说明如下:

  • proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 获取请求头 X-Forwarded-For 中的用户真实 IP, 并附加到 $proxy_add_x_forwarded_for 变量
  • if...
    • (...) 变量 $proxy_add_x_forwarded_for 不匹配正则 192\.168\.1[45] (即 192.168.14.*192.168.15.*)
    • return 403, 如果上边的条件满足, 返回 403
    • 即: 如果真实IP不是 192.168.14.*192.168.15.*, 返回403.

如果有更复杂的需求, 可以参考这个示例:

proxy_set_header HOST $http_host;
proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;

if ($http_host ~ "yourdomain.hypernode.io:8443")  {
  set $block_me_now A;
}
 
if ($proxy_add_x_forwarded_for != YOURIP) {
  set $block_me_now "${block_me_now}B";
}
 
 
if ($block_me_now = AB) {
    return 403;
    break;
}

为啥 deny 配置不起作用?

🤔 疑问: 为啥以下的配置不起作用?

allow 192.168.14.0/24;
allow 192.168.15.0/24;
deny all;

根据nginx官方文档, deny 指令是根据「client address」进行限制的.

📓 引用:

The ngx_http_access_module module allows limiting access to certain client addresses.

而「client address」对应的变量是: $remote_addr

📓 引用:

$remote_addr:
​ client address

关于 $remote_addr:

是 nginx 与客户端进行 TCP 连接过程中,获得的客户端真实地址. Remote Address 无法伪造,因为建立 TCP 连接需要三次握手,如果伪造了源 IP,无法建立 TCP 连接,更不会有后面的 HTTP 请求

remote_addr 代表客户端的 IP,但它的值不是由客户端提供的,而是服务端根据客户端的 ip 指定的,当你的浏览器访问某个网站时,假设中间没有任何代理,那么网站的 web 服务器(Nginx,Apache 等)就会把 remote_addr 设为你的机器IP,如果你用了某个代理(其实 F5 就是这个反向代理),那么你的浏览器会先访问这个代理,然后再由这个代理转发到网站,这样 web 服务器就会把 remote_addr 设为这台代理机器的 IP。

但是实际某些特殊场景中,我们即使有代理,也需要将 $remote_addr 设置为真实的用户 IP,以便记录在日志当中,当然 nginx 是有这个功能,但是需要编译的时候添加 --with-http_realip_module 这个模块,默认是没有安装的。(我也没有安装)

三人行, 必有我师; 知识共享, 天下为公. 本文由东风微鸣技术博客 EWhisper.cn 编写.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK