Caddy MaxMind GeoIP 地理访问限制:白名单与黑名单模式
目录
为什么需要 GeoIP 访问限制
当你的服务主要面向特定地区的用户时,来自其他地区的流量往往是恶意的。比如:
- 你的博客主要面向中文读者,欧洲 IP 的访问可能来自扫描器
- 管理后台只需要从你所在的国家访问
- API 服务限制特定区域的滥用
GeoIP 限制不能作为唯一的防护手段(IP 地理位置可以被 VPN 绕过),但它可以显著减少恶意流量噪音,降低服务器压力和日志噪音。
caddy-maxmind-geolocation 插件
这个插件在自定义构建时已经包含(参考 xcaddy 构建文章),它基于 MaxMind 的 GeoLite2 数据库进行 IP 地理位置查询。
数据库中每条记录包含:
- IP 段起止范围
- 所属国家代码(ISO 3166-1 alpha-2,如
CN、US、JP) - 可选的地理区域和城市信息(City 版本,本文用的是 Country 版本)
两种限制模式
我定义了两种 snippet 以适配不同场景:
白名单模式:只允许指定国家
(geo_only_allow_countries) {
@only_allow_countries_geofilter {
not {
maxmind_geolocation {
db_path "/config/geodb/GeoLite2-Country.mmdb"
allow_countries {args[:]}
}
}
}
respond @only_allow_countries_geofilter "You are blocked" 403
}逻辑:定义一个名为 @only_allow_countries_geofilter 的命名匹配器,匹配那些不在指定国家列表中的请求,对这些请求返回 403。
使用方式:
example.com {
import geo_only_allow_countries CN JP
reverse_proxy 127.0.0.1:3004
}这样就只允许从中国和日本 IP 访问。
黑名单模式:禁止指定国家
(geo_not_allow_countries) {
@not_allow_countries_geofilter {
maxmind_geolocation {
db_path "/config/geodb/GeoLite2-Country.mmdb"
allow_countries {args[:]}
}
}
respond @not_allow_countries_geofilter "You are blocked" 403
}逻辑:匹配在指定国家列表中的请求,对这些请求返回 403。
使用方式:
example.com {
import geo_not_allow_countries RU
reverse_proxy 127.0.0.1:8080
}禁止来自俄罗斯的 IP 访问。
GeoLite2 数据库自动更新
MaxMind 的 GeoLite2 数据库会随 IP 分配变化而更新,大约每月更新 1-2 次。使用过期的数据库会导致部分 IP 的地理位置判断错误。
我的容器中通过 update_geodb.sh 自动管理,在 xcaddy 文章中已经介绍。
局限性
- VPN/代理绕过:用户可以通过 VPN 切换出口 IP,GeoIP 无法阻止
- 数据库时效性:IP 段会重新分配,老数据库可能导致误判
- CDN 回源:如果请求经过 Cloudflare,Caddy 收到的 IP 是 Cloudflare 的回源 IP,需要正确配置
trusted_proxies才能获取真实客户端 IP
所以 GeoIP 应该作为一个降低攻击面的辅助手段,而不是唯一的安全屏障。
总结
caddy-maxmind-geolocation 插件让你用几行 Caddyfile 配置就能实现基于 IP 地理位置的访问控制。白名单模式适合管理后台等需要严格限制的场景,黑名单模式适合屏蔽特定地区的已知恶意流量。配合自动更新的 GeoIP 数据库,维护成本非常低。
参考链接
添加评论