To prevent my server IP from being blocked by the GFW (Great Firewall), I wanted to ensure that my server is only accessible from outside mainland China. The most effective way to achieve this is by adding firewall rules to block all inbound traffic from Chinese IP addresses.

While iptables with xt_geoip has been a popular choice for years, nftables is the modern replacement in the Linux ecosystem. However, nftables lacks built-in support for GeoIP or MMDB (MaxMind Database) lookups out of the box. To bridge this gap, we need a way to generate nftables-compatible IP sets from a GeoIP database.

In this post, I’ll share a tool I built to automate this process: Auto Update MMDB. It automatically fetches the latest GeoLite2 data, extracts Chinese network ranges, and generates the necessary nftables configuration files.

The Solution: Auto Update MMDB

I created a simple Go utility called auto-update-mmdb. It performs the following tasks:

  1. Downloads the latest GeoLite2-Country.mmdb.
  2. Parses the database to find all IPv4 and IPv6 ranges associated with China (CN).
  3. Generates nftables set files (cn4.nft and cn6.nft).
  4. Reloads nftables to apply the changes.

You can find the source code on GitHub: missuo/auto-update-mmdb.

Installation and Setup

First, we need to install the tool. You can build it from source using Go:

git clone https://github.com/missuo/auto-update-mmdb.git
cd auto-update-mmdb
go build -o /usr/local/bin/auto-update-mmdb

Once installed, you can run it manually to generate the initial IP sets:

sudo /usr/local/bin/auto-update-mmdb

This will create the following files:

  • /usr/share/GeoIP/GeoLite2-Country.mmdb
  • /etc/nftables.d/cn4.nft
  • /etc/nftables.d/cn6.nft

Automating Updates

IP addresses change over time, so it’s important to keep the database updated. We can use a systemd timer to run the update daily.

Create a service file /etc/systemd/system/auto-update-mmdb.service:

[Unit]
Description=Auto Update GeoLite2 MMDB
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/auto-update-mmdb

And a timer file /etc/systemd/system/auto-update-mmdb.timer:

[Unit]
Description=Auto Update GeoLite2 MMDB Daily

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target

Enable and start the timer:

sudo systemctl daemon-reload
sudo systemctl enable --now auto-update-mmdb.timer

Configuring nftables

Now that we have the IP sets ready, we can use them in our nftables configuration.

Edit your /etc/nftables.conf. You need to include the generated files and then reference the sets (@cn4 and @cn6) in your rules.

Here is a complete example that blocks traffic from China on a specific port (e.g., 2333), while allowing other traffic:

#!/usr/sbin/nft -f

flush ruleset

table inet filter {
    # Import the generated IP sets
    include "/etc/nftables.d/cn4.nft"
    include "/etc/nftables.d/cn6.nft"

    chain input {
        type filter hook input priority 0;

        # Allow loopback and established connections
        iifname "lo" accept
        ct state established,related accept

        # Block SSH (port 22) from China
        tcp dport 22 ip saddr @cn4 drop
        tcp dport 22 ip6 saddr @cn6 drop

        # Block China IPs on port 2333 (TCP & UDP)
        tcp dport 2333 ip saddr @cn4 drop
        udp dport 2333 ip saddr @cn4 drop
        
        tcp dport 2333 ip6 saddr @cn6 drop
        udp dport 2333 ip6 saddr @cn6 drop

        # Allow everything else by default
        accept
    }
}

Blocking All Traffic

If you want to block all inbound traffic from China, you can simplify the rules:

    # Drop all traffic from China
    ip saddr @cn4 drop
    ip6 saddr @cn6 drop

After modifying the configuration, restart nftables to apply the rules:

sudo systemctl restart nftables

Conclusion

By combining nftables with a simple automation tool, we can effectively manage geolocation-based firewall rules without relying on legacy tools or complex dependencies. This setup ensures your server remains inaccessible from specific regions while keeping the IP database up-to-date automatically.