Sistem Operasi Ubuntu Server 20.04 lts s/d Ubuntu Server 24.04 lts
Instal conntrack (jika belum ada). Ini adalah alat penting untuk memutus koneksi secara paksa.
sudo apt update && sudo apt install conntrack -y
Jalan kan perintah berikut :
sudo mkdir -p /opt/udp-proxy/bin
sudo mkdir -p /opt/udp-proxy/log
Langkah 2: Membuat Skrip Utama Penjaga
1.Buat file skrip:
sudo nano /opt/udp-proxy/bin/enforcer_service.sh
2.Salin dan tempel seluruh skrip di bawah ini.
#!/bin/bash
# =================================================================
# --- CEK FILE BENDERA (KONTROL MANUAL) ---
# =================================================================
FLAG_FILE="/opt/udp-proxy/log/enforcer.enabled"
if [ ! -f "$FLAG_FILE" ]; then
echo "[$(date)] File bendera '$FLAG_FILE' tidak ditemukan. Penjaga tidak akan dijalankan."
exit 0
fi
# =================================================================
# --- KONFIGURASI PENJAGA ---
# =================================================================
PROTECTED_PORT=36712
STATE_FILE="/opt/udp-proxy/log/enforcer_state.log"
IPTABLES_CHAIN="UDP_ENFORCER"
MEMORY_MINUTES=10
TIMEOUT_MINUTES=15
GRACE_PERIOD_SECONDS=120 # 2 menit = 120 detik
# =================================================================
# --- FUNGSI PEMBERSIH (OTOMATIS LUPA & EKSEKUSI TIMER) ---
# =================================================================
function cleanup() {
echo "[$(date)] Memulai pembersihan sesi dan pengecekan timer..."
local current_time=$(date +%s)
local timeout_seconds=$((TIMEOUT_MINUTES * 60))
local temp_state_file=$(mktemp)
if [ ! -f "$STATE_FILE" ]; then
touch "$STATE_FILE"
return
fi
while IFS=':' read -r user ip last_seen violation_time; do
if [[ -z "$user" || -z "$ip" || -z "$last_seen" ]]; then continue; fi
local elapsed=$((current_time - last_seen))
if [ "$elapsed" -lt "$timeout_seconds" ]; then
# Sesi masih aktif, periksa apakah ada timer yang perlu dieksekusi
if [[ -n "$violation_time" ]]; then
local violation_elapsed=$((current_time - violation_time))
if [ "$violation_elapsed" -ge "$GRACE_PERIOD_SECONDS" ]; then
echo "[$(date)] Timer habis. Menendang IP '$ip' untuk user '$user'..."
local rule_num=$(sudo iptables -L "$IPTABLES_CHAIN" --line-numbers -n | grep "$ip" | awk '{print $1}' | head -n 1)
if [ -n "$rule_num" ]; then
sudo iptables -D "$IPTABLES_CHAIN" "$rule_num"
echo "[$(date)] Aturan untuk IP '$ip' telah dihapus dari iptables."
fi
# Jangan tambahkan kembali ke file state, karena sudah ditendang
continue
else
# Timer belum habis, simpan kembali dengan timer
echo "${user}:${ip}:${last_seen}:${violation_time}" >> "$temp_state_file"
fi
else
# Tidak ada timer, simpan kembali seperti biasa
echo "${user}:${ip}:${last_seen}:" >> "$temp_state_file"
fi
else
# Sesi sudah kadaluarsa, bersihkan
echo "[$(date)] Sesi untuk user '$user' dari IP '$ip' telah kadaluarsa. Membuka blokir..."
local rule_num=$(sudo iptables -L "$IPTABLES_CHAIN" --line-numbers -n | grep "$ip" | awk '{print $1}' | head -n 1)
if [ -n "$rule_num" ]; then
sudo iptables -D "$IPTABLES_CHAIN" "$rule_num"
echo "[$(date)] Aturan untuk IP '$ip' telah dihapus dari iptables."
fi
fi
done < "$STATE_FILE"
mv "$temp_state_file" "$STATE_FILE"
}
#!/bin/bash
# =================================================================
# --- CEK FILE BENDERA (KONTROL MANUAL) ---
# =================================================================
FLAG_FILE="/opt/udp-proxy/log/enforcer.enabled"
if [ ! -f "$FLAG_FILE" ]; then
echo "[$(date)] File bendera '$FLAG_FILE' tidak ditemukan. Penjaga tidak akan dijalankan."
exit 0
fi
# =================================================================
# --- KONFIGURASI PENJAGA ---
# =================================================================
PROTECTED_PORT=36712
STATE_FILE="/opt/udp-proxy/log/enforcer_state.log"
IPTABLES_CHAIN="UDP_ENFORCER"
MEMORY_MINUTES=10
TIMEOUT_MINUTES=15
GRACE_PERIOD_SECONDS=120 # 2 menit = 120 detik
# =================================================================
# --- FUNGSI PEMBERSIH (OTOMATIS LUPA & EKSEKUSI TIMER) ---
# =================================================================
function cleanup() {
echo "[$(date)] =====> MEMULAI PEMBERSIHAN DAN EKSEKUSI TIMER <====="
local current_time=$(date +%s)
local timeout_seconds=$((TIMEOUT_MINUTES * 60))
local temp_state_file=$(mktemp)
if [ ! -f "$STATE_FILE" ]; then
touch "$STATE_FILE"
return
fi
while IFS=':' read -r user ip last_seen violation_time; do
if [[ -z "$user" || -z "$ip" || -z "$last_seen" ]]; then continue; fi
local elapsed=$((current_time - last_seen))
if [ "$elapsed" -lt "$timeout_seconds" ]; then
if [[ -n "$violation_time" ]]; then
local violation_elapsed=$((current_time - violation_time))
if [ "$violation_elapsed" -ge "$GRACE_PERIOD_SECONDS" ]; then
echo "[$(date)] >>> EKSEKUSI: Timer habis. Memutus koneksi IP '$ip' untuk user '$user'..."
# --- PERUBAHAN KRUSIAL 1: CONNTRACK AGRESIF ---
# Hapus SEMUA sesi UDP dari IP sumber, tanpa memandang port.
# Ini jauh lebih efektif untuk memutus koneksi.
echo "[$(date)] [DEBUG] Menjalankan: sudo conntrack -D -s $ip -p udp"
sudo conntrack -D -s "$ip" -p udp 2>/dev/null
# --- PERUBAHAN KRUSIAL 2: BLOKIR DI INPUT & FORWARD ---
# Kita blokir di kedua chain untuk memastikan tidak ada celah.
echo "[$(date)] [DEBUG] Memeriksa aturan iptables untuk IP '$ip'..."
if ! sudo iptables -C "$IPTABLES_CHAIN" -s "$ip" -j DROP &> /dev/null; then
echo "[$(date)] [DEBUG] Menjalankan: sudo iptables -A $IPTABLES_CHAIN -s $ip -j DROP"
sudo iptables -A "$IPTABLES_CHAIN" -s "$ip" -j DROP -m comment --comment "Kicked $USER on $(date +%F-%T)"
echo "[$(date)] >>> IP '$ip' telah diblokir di iptables."
else
echo "[$(date)] [DEBUG] Aturan DROP untuk IP '$ip' sudah ada."
fi
echo "[$(date)] >>> Eksekusi selesai untuk IP '$ip'."
continue
else
echo "[$(date)] [DEBUG] Timer untuk IP '$ip' user '$user' belum habis. Menunggu..."
echo "${user}:${ip}:${last_seen}:${violation_time}" >> "$temp_state_file"
fi
else
echo "[$(date)] [DEBUG] Sesi normal untuk user '$user' dari IP '$ip'."
echo "${user}:${ip}:${last_seen}:" >> "$temp_state_file"
fi
else
echo "[$(date)] Sesi untuk user '$user' dari IP '$ip' telah kadaluarsa. Membuka blokir..."
local rule_num=$(sudo iptables -L "$IPTABLES_CHAIN" --line-numbers -n | grep "$ip" | awk '{print $1}' | head -n 1)
if [ -n "$rule_num" ]; then
echo "[$(date)] [DEBUG] Menghapus aturan iptables nomor $rule_num untuk IP '$ip'."
sudo iptables -D "$IPTABLES_CHAIN" "$rule_num"
fi
fi
done < "$STATE_FILE"
mv "$temp_state_file" "$STATE_FILE"
echo "[$(date)] =====> PEMBERSIHAN SELESAI <====="
}
# =================================================================
# --- INISIALISASI PENJAGA ---
# =================================================================
mkdir -p "$(dirname "$STATE_FILE")"
touch "$STATE_FILE"
# Buat chain jika belum ada
if ! sudo iptables -L "$IPTABLES_CHAIN" &> /dev/null; then
echo "Membuat chain iptables: $IPTABLES_CHAIN"
sudo iptables -N "$IPTABLES_CHAIN"
fi
# Hubungkan ke INPUT chain
if ! sudo iptables -C INPUT -p udp --dport "$PROTECTED_PORT" -j "$IPTABLES_CHAIN" &> /dev/null; then
echo "Menghubungkan chain ke INPUT untuk port $PROTECTED_PORT"
sudo iptables -I INPUT -p udp --dport "$PROTECTED_PORT" -j "$IPTABLES_CHAIN"
fi
# --- PERUBAHAN KRUSIAL 3: HUBUNGKAN JUGA KE FORWARD CHAIN ---
# Ini penting jika server bertindak sebagai gateway.
if ! sudo iptables -C FORWARD -p udp --dport "$PROTECTED_PORT" -j "$IPTABLES_CHAIN" &> /dev/null; then
echo "Menghubungkan chain ke FORWARD untuk port $PROTECTED_PORT"
sudo iptables -I FORWARD -p udp --dport "$PROTECTED_PORT" -j "$IPTABLES_CHAIN"
fi
# Jalankan cleanup di latar belakang
while true; do
cleanup
sleep 300 # Jalankan pembersihan setiap 5 menit
done &
CLEANUP_PID=$!
trap 'kill $CLEANUP_PID; exit' SIGTERM SIGINT
# Memori awal
echo "Penjaga sedang mengingat koneksi dalam $MEMORY_MINUTES menit terakhir..."
sudo journalctl -u udp-custom.service --since "$MEMORY_MINUTES minutes ago" --no-pager | grep "Client connected" | sort | awk -F'[][]' '
{
for (i=1; i<=NF; i++) {
if ($i ~ /src:/) { split($i, s, ":"); ip = s[2]; }
if ($i ~ /user:/) { split($i, u, ":"); user = u[2]; }
}
if (user && ip) {
print user ":" ip ":" systime() ":" > "'"$STATE_FILE"'"
}
}'
awk -i inplace '!seen[$0]++' "$STATE_FILE"
echo "Memori awal selesai. Penjaga siap bertugas!"
# Loop utama pemantauan
echo "Memantau log untuk koneksi ke port $PROTECTED_PORT"
sudo journalctl -u udp-custom.service -f --no-tail | while read line; do
if [[ "$line" == *"[INFO]"*"[src:"*"[user:"*"Client connected"* ]]; then
IP=$(echo "$line" | awk -F'[][]' '{for(i=1;i<=NF;i++){if($i ~ /src:/){split($i, a, ":"); print a[2]}}}')
USER=$(echo "$line" | awk -F'[][]' '{for(i=1;i<=NF;i++){if($i ~ /user:/){split($i, a, ":"); print a[2]}}}')
if [[ -n "$IP" && -n "$USER" ]]; then
echo "[$(date)] Koneksi baru terdeteksi: User '$USER' dari IP '$IP'"
LAST_ENTRY=$(grep "^${USER}:" "$STATE_FILE" | tail -n 1)
LAST_IP=$(echo "$LAST_ENTRY" | cut -d':' -f2)
if [[ -n "$LAST_IP" && "$LAST_IP" != "$IP" ]]; then
echo "[$(date)] >>> PELANGGARAN: User '$USER' mencoba multi-login dari IP '$IP'."
echo "[$(date)] >>> IP lama '$LAST_IP' akan diputuskan dalam 2 menit."
OLD_LAST_SEEN=$(echo "$LAST_ENTRY" | cut -d':' -f3)
sed -i "/^${USER}:${LAST_IP}:/d" "$STATE_FILE"
echo "${USER}:${LAST_IP}:${OLD_LAST_SEEN}:$(date +%s)" >> "$STATE_FILE"
fi
echo "${USER}:${IP}:$(date +%s)::" >> "$STATE_FILE"
awk -i inplace '!seen[$0]++' "$STATE_FILE"
fi
elif [[ "$line" == *"[INFO]"*"[src:"*"[user:"*"Client disconnected"* ]]; then
IP=$(echo "$line" | awk -F'[][]' '{for(i=1;i<=NF;i++){if($i ~ /src:/){split($i, a, ":"); print a[2]}}}')
USER=$(echo "$line" | awk -F'[][]' '{for(i=1;i<=NF;i++){if($i ~ /user:/){split($i, a, ":"); print a[2]}}}')
if [[ -n "$IP" && -n "$USER" ]]; then
echo "[$(date)] User '$USER' dari IP '$IP' telah disconnect. Membersihkan state..."
# --- PERUBAHAN KRUSIAL 4: Hancurkan sesi saat disconnect juga ---
echo "[$(date)] [DEBUG] Disconnect. Menjalankan: sudo conntrack -D -s $ip -p udp"
sudo conntrack -D -s "$ip" -p udp 2>/dev/null
sed -i "/^${USER}:${IP}:/d" "$STATE_FILE"
fi
fi
done
# =================================================================
# --- MEMORI AWAL SAAT STARTUP ---
# =================================================================
echo "Penjaga sedang mengingat koneksi dalam $MEMORY_MINUTES menit terakhir..."
sudo journalctl -u udp-custom.service --since "$MEMORY_MINUTES minutes ago" --no-pager | grep "Client connected" | sort | awk -F'[][]' '
{
for (i=1; i<=NF; i++) {
if ($i ~ /src:/) { split($i, s, ":"); ip = s[2]; }
if ($i ~ /user:/) { split($i, u, ":"); user = u[2]; }
}
if (user && ip) {
print user ":" ip ":" systime() ":" > "'"$STATE_FILE"'"
}
}'
awk -i inplace '!seen[$0]++' "$STATE_FILE"
echo "Memori awal selesai. Penjaga siap bertugas!"
# =================================================================
# --- LOOP UTAMA PEMANTAUAN REAL-TIME ---
# =================================================================
echo "Memantau log untuk koneksi ke port $PROTECTED_PORT"
sudo journalctl -u udp-custom.service -f --no-tail | while read line; do
if [[ "$line" == *"[INFO]"*"[src:"*"[user:"*"Client connected"* ]]; then
IP=$(echo "$line" | awk -F'[][]' '{for(i=1;i<=NF;i++){if($i ~ /src:/){split($i, a, ":"); print a[2]}}}')
USER=$(echo "$line" | awk -F'[][]' '{for(i=1;i<=NF;i++){if($i ~ /user:/){split($i, a, ":"); print a[2]}}}')
if [[ -n "$IP" && -n "$USER" ]]; then
echo "[$(date)] Koneksi baru terdeteksi: User '$USER' dari IP '$IP'"
LAST_ENTRY=$(grep "^${USER}:" "$STATE_FILE" | tail -n 1)
LAST_IP=$(echo "$LAST_ENTRY" | cut -d':' -f2)
if [[ -n "$LAST_IP" && "$LAST_IP" != "$IP" ]]; then
echo "[$(date)] >>> PELANGGARAN: User '$USER' mencoba multi-login dari IP '$IP'."
echo "[$(date)] >>> IP lama '$LAST_IP' akan ditendang dalam 2 menit."
# Tandai IP lama dengan timer
OLD_LAST_SEEN=$(echo "$LAST_ENTRY" | cut -d':' -f3)
sed -i "/^${USER}:${LAST_IP}:/d" "$STATE_FILE"
echo "${USER}:${LAST_IP}:${OLD_LAST_SEEN}:$(date +%s)" >> "$STATE_FILE"
fi
# Tambahkan atau perbarui koneksi baru
echo "${USER}:${IP}:$(date +%s)::" >> "$STATE_FILE"
awk -i inplace '!seen[$0]++' "$STATE_FILE"
fi
elif [[ "$line" == *"[INFO]"*"[src:"*"[user:"*"Client disconnected"* ]]; then
IP=$(echo "$line" | awk -F'[][]' '{for(i=1;i<=NF;i++){if($i ~ /src:/){split($i, a, ":"); print a[2]}}}')
USER=$(echo "$line" | awk -F'[][]' '{for(i=1;i<=NF;i++){if($i ~ /user:/){split($i, a, ":"); print a[2]}}}')
if [[ -n "$IP" && -n "$USER" ]]; then
echo "[$(date)] User '$USER' dari IP '$IP' telah disconnect. Membersihkan state..."
# Hapus entri untuk user dan IP ini, yang membatalkan timer
sed -i "/^${USER}:${IP}:/d" "$STATE_FILE"
fi
fi
done
4.Berikan izin eksekusi:
sudo chmod +x /opt/udp-proxy/bin/enforcer_service.sh
Langkah 3: Membuat Layanan systemd
1.Buat file layanan:
sudo nano /etc/systemd/system/udp-enforcer.service
2.Salin dan tempel konfigurasi berikut:
[Unit]
Description=UDP Connection Enforcer Service
After=network.target udp-custom.service
Wants=udp-custom.service
[Service]
Type=simple
ExecStart=/opt/udp-proxy/bin/enforcer_service.sh
Restart=always
RestartSec=10
User=root
[Install]
WantedBy=multi-user.target
3.Simpan dan keluar (Ctrl+X, Y, Enter).
Langkah 4: Membuat Perintah Kontrol Manual (enforcer-on / enforcer-off)
Ini adalah kunci untuk kontrol yang "ber-ingat".
1.Buat perintah enforcer-on:
sudo nano /usr/local/bin/enforcer-on
Salin dan tempel:
#!/bin/bash
FLAG_FILE="/opt/udp-proxy/log/enforcer.enabled"
SERVICE_NAME="udp-enforcer.service"
echo "Mengaktifkan Penjaga Koneksi..."
# Buat direktori log jika belum ada untuk mencegah error
sudo mkdir -p "$(dirname "$FLAG_FILE")"
sudo touch "$FLAG_FILE"
sudo systemctl start "$SERVICE_NAME"
sudo systemctl enable "$SERVICE_NAME"
echo "Penjaga telah diaktifkan. Statusnya akan diingat setelah reboot."
2.Buat perintah enforcer-off:
sudo nano /usr/local/bin/enforcer-off
Salin dan tempel:
#!/bin/bash
FLAG_FILE="/opt/udp-proxy/log/enforcer.enabled"
SERVICE_NAME="udp-enforcer.service"
echo "Menonaktifkan Penjaga Koneksi..."
sudo systemctl stop "$SERVICE_NAME"
sudo rm -f "$FLAG_FILE"
echo "Penjaga telah dinonaktifkan. Statusnya akan diingat setelah reboot."
3.Berikan izin eksekusi pada kedua perintah:
sudo chmod +x /usr/local/bin/enforcer-on
sudo chmod +x /usr/local/bin/enforcer-off
5.Langkah 5: Finalisasi dan Aktivasi Awal
Langkah terakhir untuk menyelesaikan setup dan mengaktifkan Penjaga untuk pertama kalinya.
1.Muat ulang systemd untuk mengenali layanan baru:
sudo systemctl daemon-reload
2.Aktifkan layanan sekali saja
sudo systemctl enable udp-enforcer.service
3.Aktifkan Penjaga untuk pertama kalinya:
enforcer-on
4.Verifikasi statusnya:
sudo systemctl status udp-enforcer.service
Anda harus melihat Active: active (running).
Jalankan perintah-perintah ini secara manual untuk pengecekan urutan aturan:
sudo iptables -D INPUT -p udp --dport 36712 -j UDP_ENFORCER
sudo iptables -I INPUT 1 -p udp --dport 36712 -j UDP_ENFORCER
Sekarang, coba lagi perintah :
sudo iptables -L INPUT -n -v --line-numbers
Hasilnya harusnya terlihat seperti ini:
Chain INPUT (policy ACCEPT ...)
num pkts bytes target prot opt in out source destination
1 0 0 UDP_ENFORCER udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:36712
2 1355K 318M ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:36712
...
Sekarang UDP_ENFORCER ada di posisi #1. Sistem blokir seharusnya sudah bekerja!
Restart layanan untuk menerapkan perubahan:
sudo systemctl restart udp-enforcer.service
Ringkasan Perintah Tanpa Panel/Manual
Mengaktifkan Penjaga
enforcer-on
Menonaktifkan Penjaga
enforcer-off
Cek Status Layanan
sudo systemctl status udp-enforcer.service
Lihat Log Aktivitas
sudo journalctl -u udp-enforcer.service -f --no-pager
Lihat IP yang Diblokir
sudo iptables -L UDP_ENFORCER -n -v
Lepas Semua Blokir
sudo iptables -F UDP_ENFORCER
Hapus File State (Reset)
echo "" > /opt/udp-proxy/log/enforcer_state.log
Untuk mempermudah penggunaan. Kita akan membuat sebuah skrip menu interaktif yang bisa Anda panggil dengan perintah hunter.
Langkah 1: Membuat File Skrip hunter :
Kita akan membuat file skrip bernama hunter di direktori /usr/local/bin. Direktori ini ada di PATH sistem, artinya Anda bisa menjalankan skrip dari mana saja dengan cukup mengetik namanya.
1.Buat file skrip dengan nano:
sudo nano /usr/local/bin/hunter
2.Copy-paste seluruh kode di bawah ini ke dalam file nano:
#!/bin/bash
# Fungsi untuk menampilkan menu
show_menu() {
clear
echo "=========================================="
echo " PANEL PENJAGA UDP - HUNTER"
echo "=========================================="
echo "1. Aktifkan Penjaga UDP"
echo "2. Nonaktifkan Penjaga UDP"
echo "3. Lihat Status Penjaga"
echo "4. Pantau Log Aktivitas (Live)"
echo "5. Lihat IP yang Diblokir"
echo "6. Bersihkan Semua IP yang Diblokir"
echo "7. Keluar"
echo "=========================================="
}
# Loop utama menu
while true; do
show_menu
read -p "Masukkan pilihan Anda [1-7]: " choice
case $choice in
1)
echo ">> Mengaktifkan Penjaga..."
sudo /opt/udp-proxy/panel/enable.sh
;;
2)
echo ">> Menonaktifkan Penjaga..."
sudo /opt/udp-proxy/panel/disable.sh
;;
3)
echo ">> Status Layanan Penjaga:"
sudo systemctl status udp-enforcer.service --no-pager
;;
4)
echo ">> Menampilkan log aktivitas (tekan Ctrl+C untuk kembali ke menu):"
sudo journalctl -u udp-enforcer.service -f
;;
5)
echo ">> Daftar IP yang saat ini diblokir:"
sudo iptables -L UDP_ENFORCER -n -v --line-numbers
;;
6)
echo ">> Membersihkan semua aturan blokir IP..."
sudo iptables -F UDP_ENFORCER
echo ">> Semua IP telah dibebaskan dari blokir."
;;
7)
echo ">> Keluar dari menu Hunter. Sampai jumpa!"
exit 0
;;
*)
echo ">> Pilihan tidak valid, silakan coba lagi."
;;
esac
# Jeda sebelum menampilkan menu kembali
echo ""
read -p "Tekan [Enter] untuk melanjutkan..."
done
Langkah 2: Jadikan Skrip Dapat Dieksekusi
Agar skrip hunter bisa dijalankan, kita perlu memberinya izin eksekusi.
sudo chmod +x /usr/local/bin/hunter
Langkah 3: Cara Menggunakan Menu hunter
Sekarang, panel interaktif Anda siap digunakan!
1.Buka terminal.
2.Ketik perintah berikut untuk membuka menu:
sudo hunter
Sekarang Anda memiliki cara yang jauh lebih mudah dan cepat untuk mengelola sistem penjaga UDP Anda.





