V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
5261
V2EX  ›  程序员

小开发咨询下运维的问题,nginx 转发到 kong 网关, ip-restriction 插件失效问题

  •  
  •   5261 · 22 小时 15 分钟前 · 567 次点击

    请求流程如下

    用户请求 -> nginx -> kong 网关

    需求如下 想通过 kong 网关 ip-restriction 插件 限制部分用户的真实 ip 访问接口

    遇到的问题

    1 、kong 网关这边获取到的 X-real-ip 一直都是 nginx 节点的 ip ,导致 ip-restriction 插件失效

    nginx 部分配置

     location / {
                proxy_pass        http://a.kong.com/;
                proxy_set_header   X-Real-IP        $remote_addr;
                proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    }
    

    kong 网关配置

    server {
       server_name kong;
       listen 0.0.0.0:8000;
       error_page 400 404 408 411 412 413 414 417 494 /kong_error_handler;
       error_page 500 502 503 504 /kong_error_handler;
    
       access_log logs/access.log main;
       error_log logs/error.log notice;
    
       client_body_buffer_size 8k;
    
    
       real_ip_header     X-Real-IP;
       real_ip_recursive  off;
       set_real_ip_from 0.0.0.0/0;
       set_real_ip_from ::/0;
    
    
       include nginx-x-header.conf;
    
       location / {
           default_type                     '';
    
           set $ctx_ref                     '';
           set $upstream_host               '';
           set $upstream_upgrade            '';
           set $upstream_connection         '';
           set $upstream_scheme             '';
           set $upstream_uri                '';
           set $upstream_x_forwarded_for    '';
           set $upstream_x_forwarded_proto  '';
           set $upstream_x_forwarded_host   '';
           set $upstream_x_forwarded_port   '';
    
           rewrite_by_lua_block {
               Kong.rewrite()
           }
    
           access_by_lua_block {
               Kong.access()
           }
    
           proxy_http_version 1.1;
           proxy_set_header   Host              $upstream_host;
           proxy_set_header   Upgrade           $upstream_upgrade;
           proxy_set_header   Connection        $upstream_connection;
           proxy_set_header   X-Forwarded-For   $upstream_x_forwarded_for;
           proxy_set_header   X-Forwarded-Proto $upstream_x_forwarded_proto;
           proxy_set_header   X-Forwarded-Host  $upstream_x_forwarded_host;
           proxy_set_header   X-Forwarded-Port  $upstream_x_forwarded_port;
           proxy_set_header   X-Real-IP         $remote_addr;
           proxy_pass_header  Server;
           proxy_pass_header  Date;
           proxy_ssl_name     $upstream_host;
           proxy_pass         $upstream_scheme://kong_upstream$upstream_uri;
    
           header_filter_by_lua_block {
               Kong.header_filter()
           }
    
           body_filter_by_lua_block {
               Kong.body_filter()
           }
    
           log_by_lua_block {
               Kong.log()
           }
       }
    
       location = /kong_error_handler {
           internal;
           uninitialized_variable_warn off;
    
           content_by_lua_block {
               Kong.handle_error()
           }
    
           header_filter_by_lua_block {
               Kong.header_filter()
           }
    
           body_filter_by_lua_block {
               Kong.body_filter()
           }
    
           log_by_lua_block {
               Kong.log()
           }
       }
    }
    
    第 1 条附言  ·  1 小时 7 分钟前

    看了下 ip-restriction 插件的源代码如下

    function IpRestrictionHandler:access(conf)
      IpRestrictionHandler.super.access(self)
      local block = false
      local binary_remote_addr = ngx.var.binary_remote_addr
    
      if not binary_remote_addr then
        return responses.send_HTTP_FORBIDDEN("Cannot identify the client IP address, unix domain sockets are not supported.")
      end
    
      if conf.blacklist and #conf.blacklist > 0 then
        block = iputils.binip_in_cidrs(binary_remote_addr, cidr_cache(conf.blacklist))
      end
    
      if conf.whitelist and #conf.whitelist > 0 then
        block = not iputils.binip_in_cidrs(binary_remote_addr, cidr_cache(conf.whitelist))
      end
    
      if block then
        return responses.send_HTTP_FORBIDDEN("Your IP address is not allowed")
      end
    end
    

    代码中 最后是通过 ngx.var.binary_remote_addr 这个参数来比较的,所以最终只需要这个变量的值要设置为 用户真实 ip 即可

    最终做了以下调整实现

    修改或验证点
    
    .kong_env
    real_ip_recursive = off
    real_ip_header = X-Real-IP
    
    
    修改 nginx-kong.conf
    
    # 添加所有 Nginx 代理服务器的 IP
    set_real_ip_from  192.168.1.10/32;  # Nginx 服务器 1
    set_real_ip_from  192.168.1.11/32;  # Nginx 服务器 2
    set_real_ip_from  192.168.1.12/32;  # Nginx 服务器 3
    
    # 如果 Nginx 服务器在一个网段,也可以用 CIDR 表示
    set_real_ip_from  192.168.1.0/24;   # 整个网段
    
    kong的配置文件也要加上对应 
    # kong.conf
    trusted_ips = 192.168.1.10,192.168.1.11,192.168.1.12
    # 或者使用网段
    trusted_ips = 192.168.1.0/24
    
    nginx 配置需要修改
    
    对应的 location 配置需要修改
    
    proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Proto  $scheme;
    
    
    最后就是 kong 插件 需要配置为全局模式
    
    
    第 2 条附言  ·  1 小时 7 分钟前
    我 kong 网关版本是 0.14.x
    8 条回复    2025-01-21 15:11:39 +08:00
    swq1227
        1
    swq1227  
       21 小时 1 分钟前
    将 nginx 的 IP 添加到 kong 的 trusted_ips 中就可以获取到了
    可以参考 kong gateway 的配置
    https://docs.konghq.com/gateway/latest/reference/configuration/#trusted_ips
    5261
        2
    5261  
    OP
       20 小时 50 分钟前
    @swq1227

    感谢回复,我在 kong 的配置中加了
    set_real_ip_from 0.0.0.0/0;
    set_real_ip_from ::/0;

    甚至在 kong.conf
    中 加了
    trusted_ips = 0.0.0.0/0,::/0

    没效果

    我配置后
    重新执行 /usr/local/openresty/nginx/sbin/nginx -p /data/servers/kong -c nginx.conf
    貌似没生效
    qingzhijiusheng
        3
    qingzhijiusheng  
       20 小时 7 分钟前
    我觉得这个问题问 Claude ,你可以很快解决。
    waringid
        4
    waringid  
       19 小时 53 分钟前
    @5261 是直接指定 Nginx 的内网地址
    defunct9
        5
    defunct9  
       19 小时 48 分钟前
    开 ssh ,让我上去看看
    zpf124
        6
    zpf124  
       19 小时 40 分钟前
    kong 网关我没用过,但我看配置和 nginx 很像。那我猜问题应该是你 kong 里的 proxy 的配置问题。

    ```
    // ...
    // 注意看这里, 你 Kong 的配置文件 这里在转发到你的负载均衡之前又一次将 X-Real-Ip 的 header 重新赋值了
    // 而这里 对于 Kong 而言,访问它的 客户端就是 nginx , 所以 $remote_addr 自然就又改回 nginx 的 ip 了
    proxy_set_header X-Real-IP $remote_addr;

    proxy_pass $upstream_scheme://kong_upstream$upstream_uri;
    ```
    louhubiao
        7
    louhubiao  
       19 小时 36 分钟前
    @zpf124 应该是的,nginx 执行的顺序不是顺序执行的,全局赋值语句优先级最高,应该是 kong 里面把 X-Real-IP 给重新赋值了
    5261
        8
    5261  
    OP
       18 小时 57 分钟前
    2025-1-21 更新

    在 .kong_env 的 kong 配置文件中加入 trusted_ips 配置后,现在 X-Real-IP 是可以获取到真实的 ip 了

    但奇怪的时候 kong 的 ip-restriction 插件依然是失效的,我真要懵逼了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5819 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 18ms · UTC 02:08 · PVG 10:08 · LAX 18:08 · JFK 21:08
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.