基于地理位置的 Caddy 访问控制模块
提供两种地理位置匹配器:
- geocn: 识别来源 IP 是否为中国 IP(基于 GeoIP2)
- geocity: 精细的省市地区访问控制(基于 ip2region)
xcaddy build --with github.com/ysicing/caddy2-geocn- 🇨🇳 识别中国 IP 地址
- 🧠 IP 获取:优先使用 Caddy 的
ClientIPVarKey(需配置trusted_proxies),回退到RemoteAddr - 🔄 自动更新 GeoIP2 数据库(默认每 24h 检查)
- 🗄️ 查询结果缓存(默认启用:TTL 5m,容量 10000)
- 🚀 全局单例:所有站点共享同一数据库和缓存,资源高效
- 🏙️ 支持省份和城市级别的访问控制
- 🧠 IP 获取:优先使用 Caddy 的
ClientIPVarKey(需配置trusted_proxies),回退到RemoteAddr - 🔄 自动更新 ip2region 数据库(默认每 24h 检查)
- 🗄️ 查询结果缓存(默认启用:TTL 5m,容量 10000;可在 Caddyfile 用
cache off关闭) - 🎯 精确的地理位置识别
GeoCN 采用全局单例模式,配置在全局选项块中,所有站点共享。
{
# 如果在反向代理后面,需要配置 trusted_proxies
servers {
trusted_proxies static 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
}
}
# 只允许中国 IP 访问
china.example.com {
@china_ip geocn
handle @china_ip {
file_server
}
handle {
respond "仅限中国大陆访问" 403
}
}{
# GeoCN 全局配置(所有站点共享)
geocn {
interval 24h # 数据库更新检查间隔
timeout 30s # 下载超时
cache ttl 10m size 20000 # 缓存配置
# cache off # 关闭缓存
# source https://example.com/Country.mmdb # 自定义数据源
}
servers {
trusted_proxies static 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
}
}
# 站点 1
site1.example.com {
@cn geocn
handle @cn {
respond "Welcome from China!"
}
handle {
respond "Access denied" 403
}
}
# 站点 2(共享同一 GeoCN 实例)
site2.example.com {
@cn geocn
handle @cn {
reverse_proxy backend:8080
}
handle {
respond "仅限中国访问" 403
}
}-
默认缓存
- 开启:默认启用
- TTL:5m(
cache ttl 5m可调整) - 容量:10000(
cache size 10000可调整) - 关闭:Caddyfile 中使用
cache off,或 JSON 使用enable_cache: false
-
更新策略
- 默认每 24 小时检查更新(
interval 24h可调整) - 远端 HEAD 返回 Last-Modified 时:与本地文件 mtime 比较,变新则更新
- 远端缺少 Last-Modified 时:按
interval与本地 mtime 判断是否需要刷新
- 默认每 24 小时检查更新(
{
# 如果在反向代理后面,需要配置 trusted_proxies
servers {
trusted_proxies static 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
}
}
# 只允许北京和上海访问
city.example.com {
@allowed {
geocity {
regions "北京" "上海"
# 在整个 region 字符串中搜索
# 例如 "中国|0|北京|北京市|联通" 会匹配 "北京"
}
}
handle @allowed {
reverse_proxy backend:8080
}
handle {
respond "仅限北京、上海地区访问" 403
}
}
# 禁止特定省份访问(使用 not 匹配器)
province.example.com {
@blocked {
geocity {
regions "河北" "山东"
}
}
handle @blocked {
respond "该地区暂不提供服务" 403
}
handle {
file_server
}
}- 双栈:支持 IPv4 与 IPv6,自动按 IP 版本选择对应数据库
- 数据源:支持 HTTP URL 或本地文件(分别配置 v4/v6 源)
- 更新:默认每 24h 检查 HTTP 源是否更新,缺少 Last-Modified 时按
interval回退判断 - 缓存:默认启用(TTL 5m,容量 10000),可
cache off关闭 - IP 获取:优先使用 Caddy 的
ClientIPVarKey(需配置trusted_proxies),回退到RemoteAddr
配置项:
regions:地区关键词列表,在整个 region 字符串中搜索匹配provinces:省份列表(已废弃,建议使用 regions)cities:城市列表(已废弃,建议使用 regions)ipv4_source:IPv4 数据库源(HTTP URL 或本地文件)ipv6_source:IPv6 数据库源(HTTP URL 或本地文件)interval:更新检查间隔(默认24h,仅对 HTTP 源生效)timeout:下载/检查超时(默认30s)cache:默认启用;可配置cache ttl <duration>、cache size <number>
更多配置示例:
geocity {
# 自定义数据源(可选)
# ipv4_source https://cdn.example.com/ip2region_v4.xdb
# ipv6_source /opt/geodata/ip2region_v6.xdb
# 更新(仅 HTTP 源)与超时
interval 24h
timeout 30s
# 缓存(默认启用)
cache ttl 10m size 20000
# 关闭缓存:
# cache off
}常见用法:
- 允许部分省市访问:
geocity {
regions "广东" "浙江" "北京" "上海"
}- 双栈混合来源(IPv4 本地、IPv6 远程):
geocity {
ipv4_source /data/ip2region_v4.xdb
ipv6_source https://github.com/lionsoul2014/ip2region/raw/master/data/ip2region_v6.xdb
interval 24h
}行为说明:
- 私有/环回/链路本地/未指定/组播地址会被跳过
- 非中国 IP 返回 false(不匹配)
- 本地文件作为数据源时不参与定期更新;HTTP 源才会根据
interval检查更新 - 首次运行会自动下载数据库到
{caddy_data_dir}/geocity/ipv4.xdb与{caddy_data_dir}/geocity/ipv6.xdb
当 Caddy 位于反向代理(如 nginx、Cloudflare)后面时,需要配置 trusted_proxies 以正确获取客户端真实 IP:
{
servers {
trusted_proxies static 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
}
}
example.com {
@cn geocn
handle @cn {
respond "Welcome from China!"
}
}Cloudflare 示例:
{
servers {
trusted_proxies cloudflare
}
}注意:如果未配置
trusted_proxies,模块会回退到使用RemoteAddr,这在有反向代理时可能获取到代理服务器的 IP 而非客户端真实 IP。