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."