How to Restrict Nginx Access to Mainland China Using Free APNIC IP Data in 3 Simple Steps
This guide shows how to automatically download the latest APNIC IP allocation list, generate Nginx allow rules for Chinese IP ranges, configure the server to permit only those addresses, and set up daily updates, providing a free, low‑overhead way to block foreign traffic.
Background
Approximately 90% of automated attacks on web services originate from outside China. If a service is intended for mainland Chinese users only, restricting access to Chinese IP ranges can dramatically reduce noise without requiring commercial GeoIP databases or recompiling Nginx.
Why the APNIC solution
Free and public : APNIC publishes daily IP allocation files for every country.
No extra Nginx modules : Uses native allow / deny directives.
Authoritative source : Data is released by the Asia‑Pacific Network Information Centre.
Universal compatibility : Works on any Linux distribution and any Nginx version.
Step‑by‑step implementation
Step 1 – Retrieve Chinese IP ranges from APNIC
Download the latest allocation file (or stream it) from:
wget http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest curl -sSL https://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latestCreate a helper script /usr/local/bin/gen-cn-allow.sh that converts the file into Nginx allow statements and splits IPv4 and IPv6 into separate include files.
#!/bin/bash
# Generate Nginx allow rules from APNIC data
OUTPUT_DIR="/etc/nginx/conf.d"
mkdir -p "$OUTPUT_DIR"
echo "Downloading APNIC latest data..."
wget -qO- http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest | \
awk -F'|' \
' $2 == "CN" && $3 == "ipv4" { prefix=$4; len=32 - log($5)/log(2); print "allow " prefix "/" len ";" } \
$2 == "CN" && $3 == "ipv6" { print "allow " $4 "/" $5 ";" }' > /tmp/cn_allow.list
# Separate IPv4 and IPv6 to avoid Nginx parsing errors
grep -E 'allow [0-9]+\.' /tmp/cn_allow.list > "$OUTPUT_DIR/china-ipv4.conf"
grep -E 'allow [0-9a-fA-F:]+' /tmp/cn_allow.list > "$OUTPUT_DIR/china-ipv6.conf"
# Add a header comment with generation date
sed -i "1i# Auto‑generated from APNIC — $(date)" "$OUTPUT_DIR/china-ipv4.conf"
sed -i "1i# Auto‑generated from APNIC — $(date)" "$OUTPUT_DIR/china-ipv6.conf"
rm -f /tmp/cn_allow.list
echo "✅ China IP whitelist generated:"
echo " IPv4: $OUTPUT_DIR/china-ipv4.conf"
echo " IPv6: $OUTPUT_DIR/china-ipv6.conf"Make the script executable and run it once:
chmod +x /usr/local/bin/gen-cn-allow.sh
sudo /usr/local/bin/gen-cn-allow.shSchedule daily updates (e.g., 03:00 AM) to keep the list current:
echo "0 3 * * * root /usr/local/bin/gen-cn-allow.sh >/dev/null 2>&1" | sudo tee /etc/cron.d/update-cn-ipStep 2 – Configure Nginx to allow only Chinese IPs
Insert the generated include files at the top of the server block, before any deny directive.
server {
listen 80;
listen [::]:80;
server_name your-domain.com;
# Chinese IP whitelist (order matters)
include /etc/nginx/conf.d/china-ipv4.conf;
include /etc/nginx/conf.d/china-ipv6.conf;
# Optional: allow localhost
allow 127.0.0.1;
allow ::1;
# Block everything else
deny all;
location / {
root /var/www/html;
index index.html;
# other configuration …
}
}Key rule: Nginx evaluates allow and deny directives sequentially, so all allow statements must appear before deny all;.
Step 3 – Reload Nginx and verify
# Test configuration syntax
nginx -t
# Reload gracefully (no interruption)
nginx -s reload
# or, using systemd
systemctl reload nginxVerification examples:
From a Chinese 4G device – the site loads normally.
From an overseas proxy or VPS – the request returns 403 Forbidden.
Check logs:
tail -f /var/log/nginx/access.log | grep '403'Important considerations
CDN users : CDNs replace the client IP with the CDN node IP (often non‑Chinese). Enable the CDN’s “real‑IP” header (e.g., Cloudflare’s CF-Connecting-IP) or use the CDN’s built‑in geographic blocking instead of the Nginx rules.
IPv6 support : If the server does not listen on IPv6, remove the listen [::]:80; line and the include /etc/nginx/conf.d/china-ipv6.conf; directive.
Performance impact : The Chinese IP list contains roughly 6 000 prefixes. Nginx’s prefix‑matching algorithm handles this with negligible latency.
Alternative approaches (brief)
CDN geographic blocking : Quick deployment, automatic updates, DDoS protection, but depends on a third‑party service and may incur costs for advanced features.
iptables + ipset : Kernel‑level filtering with minimal overhead; configuration is more complex and can be tricky inside containers or NAT environments.
MaxMind GeoIP2 : Provides country‑ and city‑level granularity but requires an account, a commercial database, and Nginx compiled with the GeoIP2 module.
Conclusion
By leveraging the free APNIC IP allocation data and Nginx’s native allow/deny directives, you can build a low‑cost, transparent “digital border” that restricts access to mainland China only. The solution is fully open‑source, requires no additional modules, and works on any Linux + Nginx stack.
Xiao Liu Lab
An operations lab passionate about server tinkering 🔬 Sharing automation scripts, high-availability architecture, alert optimization, and incident reviews. Using technology to reduce overtime and experience to avoid major pitfalls. Follow me for easier, more reliable operations!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
