# Block Inbound Traffic from Mainland China

> A technical guide on using nftables with GeoIP to block inbound traffic from China, featuring a custom Go tool (auto-update-mmdb) that automatically downloads GeoLite2 database and generates IP sets for firewall rules.

Author: Vincent Yang
Published: 2025-11-19
Tags: nftables, Linux, iptables, GeoIP
Source: https://missuo.me/posts/block-china-inbound

---

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](https://github.com/missuo/auto-update-mmdb).

## Installation and Setup

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

```bash
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:

```bash
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`:

```ini
[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`:

```ini
[Unit]
Description=Auto Update GeoLite2 MMDB Daily

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target
```

Enable and start the timer:

```bash
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:

```nft
#!/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:

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

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

```bash
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.