Created
February 19, 2026 13:14
-
-
Save ishworgurung/5d75f308be86c26b7406cb48612670f4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -euf -o pipefail | |
| # Block countries by IP range using ipset + iptables | |
| # Zone files from ipdeny.com, cached locally for reliability | |
| # | |
| # Usage: ./drop.bash [--update] | |
| # --update Re-download zone files before applying rules | |
| # Install: ipset, iptables-persistent on Ubuntu | |
| ZONE_DIR="/etc/ipset-countries/zones" | |
| ZONE_URL="http://www.ipdeny.com/ipblocks/data/countries" | |
| # Countries to block: code=name | |
| declare -A COUNTRIES=( | |
| [ru]="Russia" | |
| [cn]="China" | |
| [br]="Brazil" | |
| [ro]="Romania" | |
| [pk]="Pakistan" | |
| [ua]="Ukraine" | |
| [ir]="Iran" | |
| [kp]="North Korea" | |
| ) | |
| mkdir -p "$ZONE_DIR" | |
| # Download zone files only when explicitly asked | |
| if [[ "$1" == "--update" ]]; then | |
| echo "Downloading zone files..." | |
| for code in "${!COUNTRIES[@]}"; do | |
| echo " ${COUNTRIES[$code]} ($code)" | |
| wget -q -O "$ZONE_DIR/$code.zone" "$ZONE_URL/$code.zone" | |
| done | |
| echo "Zone files updated." | |
| fi | |
| # Apply rules for each country | |
| for code in "${!COUNTRIES[@]}"; do | |
| SETNAME="${code}_zone" | |
| ZONEFILE="$ZONE_DIR/$code.zone" | |
| if [[ ! -f "$ZONEFILE" ]]; then | |
| echo "SKIP: $ZONEFILE not found for ${COUNTRIES[$code]} — run with --update first" | |
| continue | |
| fi | |
| echo "Blocking ${COUNTRIES[$code]} ($code)..." | |
| # Create or flush the ipset | |
| ipset list "$SETNAME" &>/dev/null && ipset flush "$SETNAME" || ipset create "$SETNAME" hash:net | |
| # Load IPs | |
| COUNT=0 | |
| while IFS= read -r IP; do | |
| [[ -z "$IP" || "$IP" == \#* ]] && continue | |
| ipset add "$SETNAME" "$IP" 2>/dev/null | |
| ((COUNT++)) | |
| done < "$ZONEFILE" | |
| echo " Loaded $COUNT ranges into $SETNAME" | |
| # Add iptables rule if not already present (all protocols) | |
| if ! iptables -C INPUT -m set --match-set "$SETNAME" src -j DROP 2>/dev/null; then | |
| iptables -A INPUT -m set --match-set "$SETNAME" src -j DROP | |
| fi | |
| if ! iptables -C OUTPUT -m set --match-set "$SETNAME" dst -j DROP 2>/dev/null; then | |
| iptables -A OUTPUT -m set --match-set "$SETNAME" dst -j DROP | |
| fi | |
| done | |
| echo "" | |
| echo "Done. Blocked countries: ${COUNTRIES[*]}" | |
| echo "Run 'iptables -L INPUT -n | grep zone' to verify." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment