nginx/Geo 地址匹配

按 IP 最长前缀选择配置值

nginx geo 的 CIDR 模式使用二进制 radix tree,为请求地址查找最具体的网络前缀配置。

release-1.26.3索引与查找核验 2026-10-08
相关概念

工程问题#

配置可能同时包含默认值、大网段与更具体的子网;查找需要让最长匹配前缀覆盖较宽泛的规则。

实际实现#

IPv4 和 IPv6 分别调用 32 位与 128 位 radix 查找。节点沿地址位分叉,查找途中保留已命中的配置值。

处理流程#

  1. 加载 CIDR 前缀及其值
  2. 将请求来源解析为 IP 地址
  3. 按地址位沿树向下查找
  4. 返回最具体的已匹配值

源码片段#

固定版本 · 原文摘录
src/core/ngx_radix_tree.crelease-1.26.3 · L243–L263
查看原文件
243    bit = 0x80000000;244    value = NGX_RADIX_NO_VALUE;245    node = tree->root;246247    while (node) {248        if (node->value != NGX_RADIX_NO_VALUE) {249            value = node->value;250        }251252        if (key & bit) {253            node = node->right;254255        } else {256            node = node->left;257        }258259        bit >>= 1;260    }261262    return value;263}
ngx_radix32tree_find

从最高位起逐位选择左右子树;每遇到带值节点便覆盖 value,最终返回最深的已匹配前缀值。geo 的 CIDR 模式调用此 IPv4 实现,IPv6 对应另一个 128 位函数。

变量声明在片段上方;这是逐位二叉 radix 查找,不应标为路径压缩 Patricia trie,geo ranges 模式也不使用此流程。

收益与取舍#

工程分析

带来的收益

  • 查询长度受地址位数约束
  • 共享网络前缀可复用路径

付出的代价

  • 工程分析:逐位节点增加指针和分支开销
  • 源地址可信性仍需正确配置代理链

可比较的选择

范围数组适合预处理后的地址区间;重叠前缀语义需转换为不重叠范围。

版本与适用范围#

对应 geo 的 CIDR 模式;ranges 模式采用不同表示。geo 只是映射规则,不自带地理位置数据库。

参考来源#

源码、官方文档与原始论文
01
nginx · ngx_http_geo_cidr_variable

src/http/modules/ngx_http_geo_module.c · ngx_http_geo_cidr_variable

源码release-1.26.3

相关实现与比较#

1 个相关案例
6 个匹配案例