banner
ZetoHkr

ZetoHkr

摸🐟从未停止,努力从未开始
github

Blocking access to specified area IPs with iptables and ipset (Area Ban, including Docker)

What is ipset#

ipset is a tool for efficiently managing IP address sets on Linux. You can think of it as a "container" or "list" of IP addresses, but this "list" has a very fast lookup speed, making it particularly suitable for use in firewall rules.

The role of ipset here is to manage IP address sets.

Before You Start#

The following example is about blocking overseas IPs on a server in mainland China - Ubuntu 24.04 LTS (Noble Numbat)

Ensure you have other non-network methods to access the server to recover erroneous iptables rules, such as VNC, etc.

First, we need to have a specified region's IP set, which can be obtained with the following command:

# *You can also replace it with other more comprehensive IP sets
# Download the Chinese IP address set
wget -P . http://www.ipdeny.com/ipblocks/data/countries/cn.zone

Next, install ipset

sudo apt install ipset -y

Finally, create the set

# Create a set named cnip
ipset -N cnip hash:net
# Import the IPs from the downloaded IP set into the cnip set
for i in $(cat ./cn.zone ); do ipset -A cnip $i; done

Start Blocking#

To ensure the rules take effect, you need to flush the chains, do not operate directly in a production environment, and remember to back up

# Backup the existing rules
iptables-save > ~/iptables.bak
# Flush the chains
iptables -F
iptables -X
# Allow local loopback
iptables -A INPUT -i lo -j ACCEPT
# Block all overseas IPs (IPs not in the cnip set) (only allow access from Chinese IPs in the cnip set)
iptables -A INPUT -m set ! --match-set cnip src -j DROP
# Alternatively, to disallow access from Chinese IPs, simply remove the exclamation mark "!"

Notes#

First, remember to back up the existing rules to prevent issues.

Second, you need to frequently or periodically update the IP address database.

Additionally, special chains like Docker need to be handled thoughtfully.

Finally, server restarts will cause rules to be lost; you can write a script to automatically execute iptables rules on boot.

Update 2025-02-12#

Today I tried blocking overseas IPs with Docker again (following the previous text)

If the container is in host network mode, it will be consistent with the host, and no separate changes are needed; the following situation only applies to bridge mode.

First, we need to understand that Docker bridge traffic is subject to address translation after a certain chain (specifically SNAT, source address translation). Addresses that have undergone SNAT cannot be determined to be from overseas, and SNAT occurs at the chain following the FORWARD chain, namely the POSTROUTING chain (PREROUTING→FORWARD→POSTROUTING).

Supplement: DNAT (destination address translation) occurs at the chain before the FORWARD chain, namely the PREROUTING chain.

The theory exists, and practice begins.

We only need to judge the source address, so we only need to make some adjustments on the FORWARD chain.

First, we back up the existing iptables rules: iptables-save > ~/iptables.bak

Then, copy out a new rule (named iptables-only-allow-cnip-docker) and comment out the original 2 rules:

# The meaning is to directly hand over the forwarded traffic to the DOCKER chain
# -A FORWARD -j DOCKER-USER
# -A FORWARD -j DOCKER-ISOLATION-STAGE-1

After commenting, fill in the following rules below the commented-out 2 rules

The rules of iptables are executed in order.

# The meaning is to hand over traffic from the eth0 network card that matches the cnip IP set to the DOCKER-related chains (only allow IPs from cnip)
# Note: eth0 is my local network card; if there are other network cards, add or change accordingly
-A FORWARD -i eth0 -m set --match-set cnip src -j DOCKER-USER
-A FORWARD -i eth0 -m set --match-set cnip src -j DOCKER-ISOLATION-STAGE-1
# Drop packets from the eth0 network card that do not match the cnip IP set (block IPs not from cnip)
# Note: eth0 is my local network card; if there are other network cards, add or change accordingly
-A FORWARD -i eth0 -m set ! --match-set cnip src -j DROP

After making the modifications, import the rules into iptables to make them effective.

iptables-restore < ~/iptables-only-allow-cnip-docker

Effect#

  • Docker bridge network

docker-itdog

  • Local network

host-itdog

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.