# Caddy MaxMind GeoIP 地理访问限制：白名单与黑名单模式


## 为什么需要 GeoIP 访问限制

如果服务主要面向特定地区的用户，其他地区来的流量里常会混进恶意请求。比如：

- 你的博客主要面向中文读者，欧洲 IP 的访问可能来自扫描器
- 管理后台只需要从你所在的国家访问；API 服务也可能要限制特定区域的滥用

GeoIP 限制不能当成唯一的防护手段，VPN 可以绕过 IP 地理位置判断。它更适合拿来减少恶意流量和日志噪音，也能顺带减轻一点服务器压力。

## caddy-maxmind-geolocation 插件

我用的自定义构建里已经带上这个插件（参考 [xcaddy 构建文章](/posts/custom-caddy-build)）。它基于 MaxMind 的 GeoLite2 数据库做 IP 地理位置查询。

数据库中每条记录包含：

- IP 段起止范围，以及所属国家代码（ISO 3166-1 alpha-2，如 `CN`、`US`、`JP`）
- 可选的地理区域和城市信息（City 版本，本文用的是 Country 版本）

## 两种限制模式

我写了两个 snippet，对应不同场景：

### 白名单模式：只允许指定国家

```caddyfile
(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。

使用方式：

```caddyfile
example.com {
    import geo_only_allow_countries CN JP
    reverse_proxy 127.0.0.1:3004
}
```

这样就只放行中国和日本的 IP。

### 黑名单模式：禁止指定国家

```caddyfile
(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。

使用方式：

```caddyfile
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 文章](/posts/custom-caddy-build)里已经写过。

## 局限性

1. **VPN/代理绕过**：用户可以通过 VPN 切换出口 IP，GeoIP 挡不住这个
2. **数据库时效性和 CDN 回源**：IP 段会重新分配，老数据库可能导致误判；如果请求经过 Cloudflare，Caddy 收到的 IP 是 Cloudflare 的回源 IP，需要正确配置 `trusted_proxies` 才能获取真实客户端 IP

GeoIP 更适合拿来收窄攻击面，不适合单独扛安全防护。

实际配置就是几行 Caddyfile。管理后台这类场景更适合白名单模式；要挡掉特定地区的已知恶意流量，用黑名单模式更顺手。把 GeoIP 数据库自动更新接上后，后续维护也省事。

## 参考链接

- [porech/caddy-maxmind-geolocation](https://github.com/porech/caddy-maxmind-geolocation)
- [P3TERX/GeoLite.mmdb](https://github.com/P3TERX/GeoLite.mmdb)
- [MaxMind GeoLite2](https://dev.maxmind.com/geoip/geolite2-free-geolocation-data)
- [xcaddy 构建自定义 Caddy](/posts/custom-caddy-build/)
- [Caddy Cloudflare DNS-01 质询](/posts/caddy-cloudflare-dns-challenge/)


---

> 作者: Nite  
> URL: https://www.nite07.com/zh-cn/posts/caddy-geoip-restriction/  

