You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nginx如何结合set_real_ip_from仅允许指定子网访问?

问题分析与解决方案

核心问题:指令执行顺序误解

你的两次尝试失败,根源都是没搞清楚Nginx中real_ip模块与访问控制指令的执行顺序:

  • real_ip相关指令(set_real_ip_from、real_ip_header等)会在访问控制阶段(allow/deny、geo变量计算)之前执行,直接替换$remote_addr为客户端真实IP。
  • 第一次尝试中,allow/deny检查的是已经被替换后的客户端IP,而非代理出口IP,自然全部被拒绝;第二次尝试的geo模块默认匹配$remote_addr,同样拿到的是客户端真实IP,无法实现代理子网的访问限制。

正确配置思路

要同时实现「仅允许代理出口IP访问」和「获取客户端真实IP」,需要:

  1. 保留原始的代理出口IP(即real_ip替换前的$remote_addr);
  2. 基于原始代理IP完成访问控制;
  3. 控制逻辑生效后,再用real_ip模块替换出客户端真实IP供后续业务处理。

Nginx的real_ip模块会自动将替换前的原始IP保存到$realip_remote_addr变量中,我们可以直接利用这个变量实现精准控制。

示例配置

http {
    # 1. 配置真实IP替换规则:仅信任指定代理子网的真实IP传递
    set_real_ip_from 192.168.1.0/24;  # 替换为你的代理出口IP子网
    real_ip_header X-Forwarded-For;   # 根据前端代理实际传递的真实IP头调整(如X-Real-IP)
    real_ip_recursive on;             # 多层代理场景下开启,避免误将中间代理IP识别为真实IP

    # 2. 基于原始代理IP($realip_remote_addr)定义允许访问的子网
    geo $realip_remote_addr $allow_proxy_access {
        default 0;
        192.168.1.0/24 1;  # 允许的代理出口子网
        10.0.0.0/8 1;       # 可添加多个子网
    }

    server {
        listen 80;
        server_name your-site.com;

        # 3. 拦截非允许的代理IP请求
        if ($allow_proxy_access != 1) {
            return 403;
        }

        location / {
            # 此时$remote_addr已替换为客户端真实IP,可用于后续业务处理
            proxy_pass http://your-backend-service;
            # 传递真实IP给后端
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $remote_addr;
        }
    }
}

关键细节说明

  • geo $realip_remote_addr $allow_proxy_access:明确指定geo模块基于原始代理IP($realip_remote_addr)进行匹配,完全不受real_ip替换的影响;
  • real_ip_recursive on:如果前端代理还有上层代理,开启这个参数可以让Nginx从X-Forwarded-For中解析出最原始的客户端IP,而非直接取列表第一个IP;
  • 访问控制逻辑放在server块最前面,确保非允许请求被尽早拦截,减少不必要的资源消耗。

内容的提问来源于stack exchange,提问作者theKorzh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 14:02:08