Skip to main content
  1. Posts/

Geoblocking Using IPTables and IPset

·5 mins·
iptables iptables linux
Table of Contents

Blokir akses berdasarkan negara, atau dikenal sebagai geoblocking, adalah metode yang umum digunakan oleh organisasi, perusahaan, dan administrator sistem untuk meningkatkan keamanan jaringan, membatasi akses terhadap konten tertentu, atau memenuhi kebutuhan regulasi.

Salah satu pendekatan teknis yang efisien di Linux adalah menggunakan iptables dan ipset.

IPset merupakan ekstensi kernel Linux yang memungkinkan pembuatan dan pengelolaan kumpulan alamat IP (IP tunggal, range, maupun subnet) secara efisien. Dengan ipset, ribuan hingga jutaan IP dapat dimasukkan ke dalam satu aturan iptables tanpa membebani performa sistem secara signifikan.

Blokir Berdasarkan Negara (Country Blocking)
#

Instalasi IPset
#

sudo apt-get install ipset   # Ubuntu/Debian
sudo yum install ipset       # CentOS/RHEL

Membuat IP Set
#

Untuk memblokir IP individual:

sudo ipset create blacklist hash:ip

Jika Anda ingin menambahkan subnet atau CIDR, gunakan hash:net agar lebih efisien dan tidak terkena batasan jumlah IP:

sudo ipset create blacklist hash:net

Download Daftar IP Berdasarkan Negara
#

Download daftar IP sesuai negara yang ingin diblokir. Beberapa sumber yang umum digunakan:

Biasanya daftar ini tersedia dalam format CIDR (x.x.x.x/yy).

Menambahkan IP ke IPset
#

Tambahkan IP atau subnet ke dalam set:

sudo ipset add blacklist 192.168.1.100
sudo ipset add blacklist 203.0.113.45

Contoh menambahkan subnet:

sudo ipset add blacklist 203.0.113.0/24

Integrasi dengan iptables
#

Tambahkan rule iptables untuk memblokir semua IP yang terdapat di dalam set:

sudo iptables -I INPUT -m set --match-set blacklist src -j DROP

Rule ini akan langsung menjatuhkan (DROP) semua koneksi dari IP yang ada di dalam blacklist.

Contoh Script Bash Otomatis
#

Script berikut digunakan untuk mengunduh daftar IP negara tertentu dan memasukkannya ke ipset.

#!/bin/bash

# --- Debug ---
# set -e
# set -u
# set -o pipefail
# set -x

# Script untuk memblokir/membuka blokir akses dari negara tertentu menggunakan iptables dan ipset.
# Sumber data IP diambil dari repository GitHub ipverse.net.
#
# Cara Penggunaan:
# 1. Blokir negara:
#    sudo ./blokir-negara.sh block CN RU
#    atau dengan file konfigurasi:
#    sudo ./blokir-negara.sh block
#
# 2. Buka blokir negara:
#    sudo ./blokir-negara.sh remove CN RU
#    atau dengan file konfigurasi:
#    sudo ./blokir-negara.sh remove
#
# Buat file `countries.txt` di direktori yang sama dengan script untuk mode konfigurasi.
# Isi dengan kode negara per baris (misal: CN, RU, KR).

# --- Konfigurasi ---
iptables_cmd=$(command -v iptables)
ipset_cmd=$(command -v ipset)
temp_dir="/tmp"
source_url="https://raw.githubusercontent.com/ipverse/country-ip-blocks/master/country/"
config_file="$(dirname "$0")/countries.txt"

log() {
    local message="$1"
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $message"
    logger -t "blokir-negara" "$message"
}

tampilkan_cara_penggunaan() {
    echo "Cara Penggunaan: $0 <block|remove> [kode_negara1] [kode_negara2] ..."
    echo "  Jika tidak ada kode negara yang diberikan, script akan membaca dari '$config_file'."
    echo "Contoh:"
    echo "  $0 block CN RU"
    echo "  $0 remove CN"
}

download_country_ips() {
    local country_code="$1"
    local zone_file="${temp_dir}/${country_code}.cidr"
    local download_url="${source_url}${country_code}/ipv4-aggregated.txt"

    if wget -q -O "$zone_file" "$download_url"; then
        echo "$zone_file"
    else
        log "ERROR: Gagal mengunduh data untuk kode negara '${country_code}'. URL: ${download_url}"
        return 1
    fi
}

block_country() {
    local country_code="$1"
    log "Memproses negara: ${country_code} (MODE: BLOCK)"

    local zone_file
    zone_file=$(download_country_ips "$country_code")
    if [ $? -ne 0 ] || [ -z "$zone_file" ]; then
        return 1 # Gagal mengunduh
    fi

    # Hapus aturan lama jika ada untuk idempotensi
    $ipset_cmd flush "$country_code" &>/dev/null
    $iptables_cmd -D INPUT -m set --match-set "$country_code" src -j DROP &>/dev/null

    # Buat set ipset baru
    log "  Membuat set ipset baru: ${country_code}"
    $ipset_cmd list "$country_code" &>/dev/null || $ipset_cmd create "$country_code" hash:net

    # Tambahkan semua IP CIDR ke dalam set ipset
    log "  Menambahkan blok IP ke dalam set..."
    $ipset_cmd restore -exist <<-EOF
 $(grep -v '^#' "$zone_file" | sed -e "s/^/add $country_code /")

EOF

    # Terapkan aturan iptables
    log "  Menerapkan aturan iptables..."
    $iptables_cmd -I INPUT -m set --match-set "$country_code" src -j DROP

    log "  ✓ Berhasil memblokir negara ${country_code}."
    rm -f "$zone_file"
}

unblock_country() {
    local country_code="$1"
    log "Memproses negara: ${country_code} (MODE: REMOVE)"

    # Hapus aturan iptables
    local rule_num
    rule_num=$($iptables_cmd -L INPUT --line-numbers -n | grep -E "match-set $country_code src" | awk '{print $1}')
    if [ -n "$rule_num" ]; then
        log "  Menghapus aturan iptables nomor ${rule_num}..."
        $iptables_cmd -D INPUT "$rule_num"
    else
        log "  Aturan iptables untuk ${country_code} tidak ditemukan."
    fi

    # Hapus set ipset
    if $ipset_cmd list "$country_code" &>/dev/null; then
        log "  Menghapus set ipset: ${country_code}..."
        $ipset_cmd destroy "$country_code"
    else
        log "  Set ipset untuk ${country_code} tidak ditemukan."
    fi

    log "  ✓ Berhasil membuka blokir negara ${country_code}."
}


# --- Validasi Awal ---
if [ "$(id -u)" -ne 0 ]; then
   log "ERROR: Script ini harus dijalankan dengan hak akses root (gunakan sudo)." >&2
   exit 1
fi

if [ $# -lt 1 ]; then
    log "ERROR: Masukkan mode operasi (block/remove)."
    tampilkan_cara_penggunaan
    exit 2
fi

if ! command -v $iptables_cmd &> /dev/null; then
    log "ERROR: '$iptables_cmd' tidak ditemukan. Pastikan iptables terinstall." >&2
    exit 3
fi

if ! command -v $ipset_cmd &> /dev/null; then
    log "ERROR: '$ipset_cmd' tidak ditemukan. Silakan install ipset terlebih dahulu." >&2
    exit 4
fi

# --- Proses Utama ---
mode="$1"
shift # Hapus argumen pertama (mode) dari daftar argumen

countries=("$@") # Sisanya adalah daftar negara

if [ ${#countries[@]} -eq 0 ]; then
    if [ -f "$config_file" ]; then
        log "Tidak ada kode negara yang diberikan. Membaca dari '$config_file'."
        readarray -t countries < "$config_file"
        # Hapus whitespace/enter di setiap baris
        countries=("${countries[@]// /}")
        countries=("${countries[@]//$'\n'/}")
        countries=("${countries[@]//$'\r'/}")
    else
        log "ERROR: Tidak ada kode negara yang diberikan dan file '$config_file' tidak ditemukan."
        tampilkan_cara_penggunaan
        exit 5
    fi
fi

# Jalankan berdasarkan mode
case "$mode" in
    block)
        for country_code in "${countries[@]}"; do
            block_country "$(echo "$country_code" | tr '[:upper:]' '[:lower:]')"
        done
        ;;
    remove)
        for country_code in "${countries[@]}"; do
            unblock_country "$(echo "$country_code" | tr '[:upper:]' '[:lower:]')"
        done
        ;;
    *)
        log "ERROR: Mode operasi '$mode' tidak valid. Gunakan 'block' atau 'remove'."
        tampilkan_cara_penggunaan
        exit 6
        ;;
esac

log "Proses selesai."

Related

Implementing Firewall for VMs with IPtables
·3 mins
iptables linux iptables kvm libvirt
IPtables Cheatsheet
·9 mins
iptables linux iptables
Cara Menampilkan Timestamp di History Linux
·1 min
linux linux
Mengubah Tanggal Modifikasi File di Linux
·1 min
linux linux
Create Simple Systemd Service in Linux
·2 mins
linux linux
How to Copy Text in Tmux to System Clipboard
·3 mins
tmux linux tmux