基于CoreDNS建设GSLB,按照地理位置智能解析IP

详细讲解如何基于 CoreDNS 的 geoip + view 插件实现地理位置感知解析(GSLB),让不同国家/地区的用户自动解析到最近的服务器节点,提升访问体验并降低跨区域网络延迟。

上一篇文章基于 CoreDNS 完成了 cncfstack.com 域名解析从阿里云DNS迁移到自建的 CoreDNS 服务器,这篇文章是继续通过 CoreDNS 建设 GSLB 来解决不同地理位置用户解析不同 IP 的问题。

之所以要按地域解析是因为根据藏云阁流量请求来源分析,平台的很大一部分流量是来自海外的,而海外的用户实际上不需要访问藏云阁平台服务,评估结论是:这些请求大概率是网络爬虫或者AI搜索的无价值请求。并且这些请求又大量的消耗系统的资源,所以需要将海外的用户请求屏蔽掉,其中一种解决方法就是通过将域名解析到一个特殊的 IP 上来处理。

这个业务需求场景的和落地解决方案就是基于 CoreDNS 的 geoip + view 插件实现地理位置感知解析(GSLB),让不同国家/地区的用户自动解析到最近的服务器节点,提升访问体验并降低跨区域网络延迟。

目录:

  • 什么是 GSLB(全局服务器负载均衡)
  • CoreDNS 实现地理感知解析的核心插件
  • 环境准备与 GeoIP 数据库配置
  • CoreDNS 地理感知解析配置
    • 步骤一:获取 MaxMind GeoIP 数据库
    • 步骤二:编写 Corefile 配置
    • 步骤三:编写区域 zone 文件
    • 步骤四:验证解析效果
  • 总结

互联网服务的用户遍布全球,不同地区的用户访问同一个服务器时,网络延迟差异巨大。GSLB(Global Server Load Balancing,全局服务器负载均衡) 通过 DNS 层面将用户请求智能路由到地理位置最近的服务器节点,是解决跨地域访问延迟的核心技术。

传统 GSLB 方案通常依赖商业硬件设备(如 F5 GTM)或云厂商的付费 DNS 产品(如 AWS Route 53、阿里云全局流量管理),成本较高。而 CoreDNS 作为 CNCF 毕业的开源 DNS 服务器,通过其插件架构可以低成本实现地理感知解析,本文详细介绍实现方案。

什么是 GSLB(全局服务器负载均衡)

GSLB 的核心思路是在 DNS 解析阶段,根据请求来源的 地理位置 返回不同的解析结果。

举个例子:假设 www.example.com 在北京、新加坡、法兰克福分别部署了服务器:

用户在北京     → 解析到 北京服务器 1.1.1.1
用户在新加坡    → 解析到 新加坡服务器 2.2.2.2
用户在德国     → 解析到 法兰克福服务器 3.3.3.3

GSLB 的工作流程

  1. 用户发起 DNS 查询 www.example.com
  2. DNS 服务器获取客户端 IP 地址
  3. DNS 服务器查询该 IP 所属的地理位置(国家/城市)
  4. DNS 服务器根据地理位置返回对应的解析记录
  5. 用户连接到最近的服务器节点

相比基于 BGP Anycast 的方案,GSLB 的优势在于可以 精确控制 不同区域用户的解析目标,并且可以根据服务器负载、健康状态等动态调整。

CoreDNS 实现地理感知解析的核心插件

CoreDNS 实现地理感知解析需要三个核心插件的配合:

插件 作用 是否内置
geoip 根据客户端 IP 查询 GeoIP 数据库,将地理位置信息(国家、城市、经纬度等)注入请求 metadata ✅ 内置
metadata 收集和传递插件间的元数据,让 geoip 的地理信息能被 view 插件读取 ✅ 内置
view 根据表达式条件(如 metadata('geoip/country/code') == 'CN')将 DNS 请求路由到不同的 server block,返回不同解析结果 ✅ 内置(v1.10.0+)

插件协作关系

DNS 请求 → geoip 查询地理位置 → metadata 存储地理标签 → view 匹配条件 → 返回对应区域解析

注意:view 插件从 CoreDNS v1.10.0 开始内置,使用前请确认 CoreDNS 版本 ≥ 1.10.0。推荐使用 v1.11.0+ 以获得更好的稳定性。

环境准备与 GeoIP 数据库配置

MaxMind GeoIP 数据库

CoreDNS 的 geoip 插件需要 .mmdb 格式的 GeoIP 数据库。推荐使用 MaxMind GeoLite2(免费版本),也可以使用商业版 GeoIP2 获得更高精度。藏云阁 CoreDNS 使用就是免费版本。

获取 GeoLite2-City 数据库

  1. 注册 MaxMind 账户
  2. 登录后进入「Download Databases」页面
  3. 下载 GeoLite2-Country.mmdb

也可以使用其他兼容 .mmdb 格式的数据源,如 IPinfo 或 IPtoASN。

数据库定期更新

IP 地理位置数据会随时间变化(IP 分配变动、新增网段等),建议设置定期更新机制。MaxMind 提供 geoipupdate 工具自动更新:

# 安装 geoipupdate
apt-get install geoipupdate

# 配置 /etc/GeoIP.conf
AccountID your_account_id
LicenseKey your_license_key
EditionIDs GeoLite2-City
DatabaseDirectory /opt/geoip2/db

设置 crontab 每周自动更新:

0 3 * * 0 /usr/bin/geoipupdate && docker restart coredns

CoreDNS 地理感知解析配置

步骤一:获取 MaxMind GeoIP 数据库

将下载的 GeoLite2-Country.mmdb 文件放置到 CoreDNS 可以访问的路径,例如 /data/coredns/GeoLite2-Country_20260605/GeoLite2-Country.mmdb

使用 Docker Compose 部署,需要将该文件挂载到容器内:

services:
  coredns:
    image: registry.cncfstack.com/docker.io/coredns/coredns:1.14.3
    container_name: coredns
    restart: unless-stopped
    ports:
      - "53:53/udp"
      - "53:53/tcp"
      - "5380:5380/tcp"
      - "9153:9153/tcp"
    volumes:
      - ./Corefile:/Corefile
      - ./zones:/zones
      - /data/coredns/GeoLite2-Country_20260605/GeoLite2-Country.mmdb:/data/coredns/GeoLite2-Country_20260605/GeoLite2-Country.mmdb
    command: -conf /Corefile

步骤二:编写 Corefile 配置

以下是按国家/地区做地理感知解析的完整 Corefile 配置:

这里按照地域解析分了3块:中国区,美国区和全球默认区。本来是想分2个区,但是藏云阁的资源搜索在 Bing/Google 上的权重很高不可放弃,所以就多添加了一个美国区,其他国家就走默认的解析。

# 中国区视图 - 独立server块
cncfstack.com {
    view china {
        expr metadata('geoip/country/code') == 'CN'
    }
    geoip /data/coredns/GeoLite2-Country_20260605/GeoLite2-Country.mmdb {
        edns-subnet
    }
    metadata
    file /zones/cncfstack.com.china.db cncfstack.com {
        reload 30s
    }
    loadbalance round_robin
}

# 美国区视图
# bing/google搜索引起需抓取网站
cncfstack.com {
    view usa {
        expr metadata('geoip/country/code') == 'US'
    }
    geoip /data/coredns/GeoLite2-Country_20260605/GeoLite2-Country.mmdb {
        edns-subnet
    }
    metadata
    file /zones/cncfstack.com.china.db cncfstack.com {
        reload 30s
    }
    loadbalance round_robin
}

# 全球默认视图(兜底)- 必须放在最后
cncfstack.com {
    file /zones/cncfstack.com.global.db cncfstack.com {
        reload 30s
    }
}

关键配置说明

  • view 的 expr 表达式:使用 metadata('geoip/country/code') 获取客户端国家代码(如 CN、US)
  • geoip 和 metadata 插件:每个带 view 的 server block 中都需要声明
  • server block 顺序很重要:带 view 的 block 必须放在前面,不带 view 的默认 block 必须放在最后

步骤三:编写区域 zone 文件

根据上述 Corefile,需要创建2个区域 zone 文件(CN和US使用同一个解析文件)。

中国/美国区域 zonezones/cncfstack.com.china.db):

$TTL 60

@   IN  SOA ns1.cncfstack.com. support.cncfstack.com. (
        2026060101
        7200
        3600
        1209600
        3600
)

@       IN  NS      ns1.cncfstack.com.
@       IN  NS      ns2.cncfstack.com.

ns1     IN  A       1.2.3.4
ns2     IN  A       5.6.7.8

; 中国用户解析到北京服务器
@       IN  A       1.1.1.1
www     IN  A       1.1.1.1

其他区域 zonezones/cncfstack.com.global.db):

$TTL 60

@   IN  SOA ns1.cncfstack.com. support.cncfstack.com. (
        2026060101
        7200
        3600
        1209600
        3600
)

@       IN  NS      ns1.cncfstack.com.
@       IN  NS      ns2.cncfstack.com.

ns1     IN  A       1.2.3.4
ns2     IN  A       5.6.7.8

; 亚洲用户解析到新加坡服务器
@       IN  A       2.2.2.2
www     IN  A       2.2.2.2

提示:不同 zone 文件中的 SOA serial(如 2026060101)建议保持一致,避免区域传送时出现同步问题。

步骤四:验证解析效果

使用 dig 命令配合 EDNS Client Subnet(ECS)模拟来自不同地区的 DNS 查询:

同时验证2个 ns server 的状态和解析是否正常

#!/bin/bash
for dns in ns1.cncfstack.com ns2.cncfstack.com
do
    echo "========== $dns ========================================"

    echo "$dns => 测试美国"
    dig @${dns} +short www.cncfstack.com +subnet=8.8.8.8
    sleep 1

    echo "$dns => 测试英国"
    dig @${dns} +short www.cncfstack.com +subnet=4.158.180.16
    sleep 1
done

注意+subnet 参数只有在 Corefile 中配置了 edns-subnet 选项时才会生效。如果不使用 ECS,geoip 插件将使用 DNS 请求的真实源 IP 进行地理位置查询。在生产环境中,建议 启用 edns-subnet ,因为用户通常通过递归 DNS(如 8.8.8.8、114.114.114.114)发起查询,源 IP 是递归 DNS 的地址而非用户真实 IP。

总结

通过以上配置,可以实现基于地理位置的 DNS 解析,实现不同地区用户访问不同的 GSLB 服务器。相比传统商业方案,可以大幅降低多地域 DNS 调度的成本。

但也存在一些不足和注意事项:

  1. 内置的 geoip + view 插件可以实现基于地理位置返回不同的 zone 文件,但缺少 健康检查动态负载均衡 能力。如果需要更高级的 GSLB 功能,可以使用社区维护的 CoreDNS-GSLB 外部插件。

  2. GeoIP 数据库需要定期更新,免费版本建议每周更新一次。免费版本数据精度不足,更新频率受限,如果需要更详细的数据(如IP所属城市,运营商),或者更高频率的更新,可以选择企业版本。

  3. 每次 DNS 查询都会查询 .mmdb 数据库,对性能有一定的影响。但 CoreDNS 会将数据库加载到内存中,查询性能影响较小(微秒级)。