import os import requests import json import ipaddress from dotenv import load_dotenv # Load configuration dari file .env load_dotenv() BGP_ROUTER_IP = os.getenv("BGP_ROUTER_IP") BGP_ROUTER_USER = os.getenv("BGP_ROUTER_USER") BGP_ROUTER_PASSWORD = os.getenv("BGP_ROUTER_PASSWORD") # URL API RouterOS v7 untuk membaca tabel routing API_URL = f"http://{BGP_ROUTER_IP}/rest/routing/route" # Kredensial basic auth auth = (BGP_ROUTER_USER, BGP_ROUTER_PASSWORD) def get_local_bgp_routes(): """Mengambil daftar IP lokal dari address-list 'bgp-export' di router BGP. Prosedurnya: 1. Triggers script 'bgp_lokal_export' via SSH background command. 2. API polling ke /log MikroTik mencari string 'BGP Export: selesai'. 3. Setelah tercapai secara proporsional (~15K IPs), list diekstrak. """ import urllib3 import time import subprocess from datetime import datetime urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) print(f"Menghubungi router {BGP_ROUTER_IP} via SSH untuk trigger script...") # 1. Jalankan script di Mikrotik via SSH background command try: ssh_cmd = [ "sshpass", "-p", BGP_ROUTER_PASSWORD, "ssh", "-o", "StrictHostKeyChecking=no", "-o", "ConnectTimeout=10", f"{BGP_ROUTER_USER}@{BGP_ROUTER_IP}", "/system/script run bgp_lokal_export" ] # Run process asynchronous di background (-n/& setara dengan Popen) # Jangan terminate proses Python sebelum SSH selesai, agar RouterOS tidak kill script-nya! subprocess.Popen(ssh_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) print(" -> Script 'bgp_lokal_export' berhasil di-trigger via SSH.") except Exception as e: print(f" -> Gagal trigger script via SSH: {e}") print(" -> Melanjutkan dengan data bgp-export yang ada (jika ada).") session = requests.Session() session.auth = auth session.verify = False api_url = f"http://{BGP_ROUTER_IP}/rest" # 2. Polling Log MikroTik setiap 5 detik hingga ketemu indikasi BGP selesai print("Memonitor log MikroTik untuk indikasi selesai...") found_completion = False start_time = time.time() max_wait_time = 600 # 10 menit maksimal wait import re while time.time() - start_time < max_wait_time: try: log_res = session.get(f"{api_url}/log", timeout=10) if log_res.status_code == 200: logs = log_res.json() # Batasi pengecekan pada 50 baris terakhir log recent_logs = logs[-50:] if len(logs) > 50 else logs for lg in recent_logs: msg = lg.get("message", "") if re.search(r"BGP Export.*selesai total", msg): print(f" -> Indikator selesai terdeteksi di log: '{msg}'") found_completion = True break if found_completion: break except Exception as e: pass time.sleep(5) if not found_completion: print(" -> Waktu tunggu habis tapi tidak menemukan indikator log 'selesai total'.") print(" -> Melanjutkan mencoba membaca bgp-export...") print("Mengambil address-list 'bgp-export' dari router...") try: res = session.get(f"{api_url}/ip/firewall/address-list", params={"list": "bgp-export", ".proplist": "address"}, timeout=60) if res.status_code == 200: data = res.json() routes = [r.get("address") for r in data if r.get("address")] # Hapus default routes routes = [r for r in routes if r not in ("0.0.0.0/0", "::/0")] print(f" -> Berhasil: {len(routes)} rute lokal") return list(set(routes)) else: print(f" -> Error: {res.status_code} - {res.text[:100]}") return [] except Exception as e: print(f" -> Gagal: {e}") return [] def generate_address_list_script(route_list, list_name, filename): """Membentuk file .rsc yang berisi perintah create address-list MikroTik""" if not route_list: print(f"List kosong, tidak ada rute LOKAL yang ditemukan.") return print(f"Membuat file {filename} dengan {len(route_list)} subnet IP...") with open(filename, "w") as f: f.write(f"# Dibuat otomatis via Script API Python\n") f.write(f"/ip firewall address-list\n") # Bersihkan list lama sebelum memasukkan yang baru f.write(f"remove [find list=\"{list_name}\"]\n") for ip in route_list: f.write(f"add list={list_name} address=\"{ip}\"\n") print(f"File {filename} berhasil dibuat.") if __name__ == "__main__": if not all([BGP_ROUTER_IP, BGP_ROUTER_USER, BGP_ROUTER_PASSWORD]): print("Error: Variabel kredensial/BGP_ROUTER_IP belum diset dengan benar di file .env") exit(1) print("--- Memulai Proses Ekstraksi Ringan Routing LOKAL ---") local_ips = get_local_bgp_routes() if local_ips: print(f"\nRingkasan:") print(f"Total Subnet IP Lokal & CDN: {len(local_ips)}") # SAFETY CROSS-CHECK: Pastikan jumlah rute masuk akal # Karena rata-rata BGP lokal ada ~15.000+, kita set batas minimal aman 13.000 if len(local_ips) < 13000: print(f"\n[ERROR] Validasi GAGAL! Rute yang diekstrak hanya {len(local_ips)}.") print("Terdapat kemungkinan proses export di Router BGP belum selesai atau terputus.") print("Membatalkan seluruh deployment untuk mencegah router distribusi kehilangan address list.") exit(1) print(f"Membuat file routing-lokal.rsc dengan {len(local_ips)} subnet IP...") # Generate script address-list khusus untuk trafik Lokal generate_address_list_script(local_ips, "ip-lokal", "routing-lokal.rsc") print("\nSelesai! File routing-lokal.rsc siap di-upload ke router distribusi.") print("Di Router Distribusi jalankan perintah: /import file-name=routing-lokal.rsc") else: print("\nGagal mengambil rute BGP lokal. File routing-lokal.rsc tidak dibuat.") exit(1)