Instalasi Dan Konfigurasi Bird 2

Pre Install

Tunning di sisi konfigurasi

Agar traffic yang lewat bisa di forward aktifkan berikut

nano /etc/sysctl.conf

Uncomment bagian berikut

#net.ipv4.ip_forward=1

Sehingga menjadi seperti berikut

net.ipv4.ip_forward=1

Muat ulang konfigurasi

sysctl -p

Atau, Konfigurasi sysctl lanjutan untuk tweaking yang kiranya sangat berguna

# KONFIGURASI DIBAWAH DITAMBAHKAN MANUAL

fs.file-max = 16777216
fs.nr_open = 1073741824
kernel.hung_task_timeout_secs = 0
kernel.msgmax = 65536
kernel.msgmnb = 65536
net.core.default_qdisc = cake
net.core.netdev_max_backlog = 30000
net.core.rmem_default = 67108864
net.core.rmem_max = 67108864
net.core.somaxconn = 65536
net.core.wmem_max = 67108864
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.all.arp_announce = 1
net.ipv4.conf.all.arp_filter = 1
net.ipv4.conf.all.arp_ignore = 2
net.ipv4.conf.all.forwarding = 1
net.ipv4.conf.all.ignore_routes_with_linkdown = 1
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.fib_multipath_use_neigh = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_errors_use_inbound_ifaddr = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.icmp_msgs_per_sec = 2500
net.ipv4.icmp_ratelimit = 0
net.ipv4.igmp_max_memberships = 100
net.ipv4.ip_forward = 1
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.neigh.default.base_reachable_time_ms = 14400000
net.ipv4.neigh.default.gc_thresh1 = 1024
net.ipv4.neigh.default.gc_thresh2 = 2048
net.ipv4.neigh.default.gc_thresh2 = 8192
net.ipv4.neigh.default.gc_thresh3 = 4096
net.ipv4.neigh.default.gc_thresh3 = 16384
net.ipv4.route.max_size = 1073741824
net.ipv4.tcp_congestion_control = bbr
net.ipv4.tcp_dsack = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 120
net.ipv4.tcp_l3mdev_accept = 1
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_mem = 4194304 16777216 67108864
net.ipv4.tcp_no_metrics_save = 1
net.ipv4.tcp_rmem = 4194304 16777216 67108864
net.ipv4.tcp_sack = 1
net.ipv4.tcp_syn_retries = 3
net.ipv4.tcp_synack_retries = 3
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_wmem = 4194304 16777216 67108864
net.ipv6.conf.all.accept_ra_defrtr = 0
net.ipv6.conf.all.accept_ra_pinfo = 0
net.ipv6.conf.all.accept_ra_rtr_pref = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.all.autoconf = 0
net.ipv6.conf.all.dad_transmits = 0
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.all.ignore_routes_with_linkdown = 1
net.ipv6.conf.all.router_solicitations = -1
net.ipv6.icmp.ratelimit = 0
#net.ipv6.conf.all.send_redirects = 0
net.ipv6.neigh.default.base_reachable_time_ms = 14400000
net.ipv6.neigh.default.gc_thresh1 = 1024
net.ipv6.neigh.default.gc_thresh2 = 2048
net.ipv6.neigh.default.gc_thresh2 = 8192
net.ipv6.neigh.default.gc_thresh3 = 4096
net.ipv6.neigh.default.gc_thresh3 = 16384
net.ipv6.route.max_size = 32768000
vm.max_map_count = 1048575
vm.swappiness = 100

net.ipv6.conf.all.accept_ra = 0
#net.ipv6.conf.all.proxy_ndp = 1

#net.netfilter.nf_conntrack_acct = 1
#net.netfilter.nf_conntrack_checksum = 0
#net.netfilter.nf_conntrack_max = 65535
#net.netfilter.nf_conntrack_tcp_timeout_established = 7440
#net.netfilter.nf_conntrack_udp_timeout = 60
#net.netfilter.nf_conntrack_udp_timeout_stream = 180
#net.netfilter.nf_conntrack_helper = 1

# net.ipv6.conf.all.disable_ipv6 = 1

Syctl patut dicoba

# ==============================================================================
# 1. FILE SYSTEM & MEMORY TUNING
# ==============================================================================
fs.file-max = 16777216
fs.nr_open = 1073741824
vm.max_map_count = 1048575
# Mencegah OS memindahkan proses BIRD2/RAM routing ke Swap
vm.swappiness = 10
kernel.hung_task_timeout_secs = 0

# ==============================================================================
# 2. IP FORWARDING & ROUTING
# ==============================================================================
net.ipv4.ip_forward = 1
net.ipv4.conf.all.forwarding = 1
net.ipv6.conf.all.forwarding = 1

net.ipv4.conf.all.ignore_routes_with_linkdown = 1
net.ipv6.conf.all.ignore_routes_with_linkdown = 1
net.ipv4.route.max_size = 1073741824
net.ipv6.route.max_size = 32768000

# ==============================================================================
# 3. BGP ECMP MULTIPATH HASHING (L3 + L4)
# ==============================================================================
net.ipv4.fib_multipath_use_neigh = 1
net.ipv4.fib_multipath_hash_policy = 1
net.ipv6.fib_multipath_hash_policy = 1

# ==============================================================================
# 4. TABEL ARP / NEIGHBOR (FIXED OVERFLOW & BASE TIME)
# ==============================================================================
net.ipv4.neigh.default.gc_thresh1 = 8192
net.ipv4.neigh.default.gc_thresh2 = 32768
net.ipv4.neigh.default.gc_thresh3 = 65536

net.ipv6.neigh.default.gc_thresh1 = 8192
net.ipv6.neigh.default.gc_thresh2 = 32768
net.ipv6.neigh.default.gc_thresh3 = 65536

# Nilai reachable time standar (30 detik) agar ARP stale cepat dibersihkan
net.ipv4.neigh.default.base_reachable_time_ms = 30000
net.ipv6.neigh.default.base_reachable_time_ms = 30000

# ARP Filtering & Proxy
net.ipv4.conf.all.arp_announce = 1
net.ipv4.conf.default.arp_announce = 1
net.ipv4.conf.all.arp_ignore = 2
net.ipv4.conf.default.arp_ignore = 2
net.ipv4.conf.all.arp_filter = 1
net.ipv4.conf.default.arp_filter = 1

# ==============================================================================
# 5. SECURITY & RPF FILTER
# ==============================================================================
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0

net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0

net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0
net.ipv6.conf.all.accept_ra = 0
net.ipv6.conf.default.accept_ra = 0
net.ipv6.conf.all.autoconf = 0
net.ipv6.conf.default.autoconf = 0

# ==============================================================================
# 6. BUFFER & CONGESTION CONTROL
# ==============================================================================
net.core.default_qdisc = fq_codel
net.ipv4.tcp_congestion_control = bbr

net.core.netdev_max_backlog = 250000
net.core.somaxconn = 65536

net.core.rmem_default = 8388608
net.core.rmem_max = 67108864
net.core.wmem_default = 8388608
net.core.wmem_max = 67108864

net.ipv4.tcp_rmem = 4096 87380 67108864
net.ipv4.tcp_wmem = 4096 65536 67108864
net.ipv4.tcp_mem = 4194304 16777216 67108864

# TCP Behavior Optimization
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_dsack = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 120
net.ipv4.tcp_max_syn_backlog = 16384

Set CPU ke mode performance

cpufreq-set -g performance
  • Memaksa CPU untuk berjalan di kecepatan maksimum setiap saat.
  • Tidak akan mengurangi frekuensi CPU walaupun sistem sedang idle.
  • Cocok untuk server, router, dan sistem dengan kebutuhan latency rendah dan performa stabil.

Tunning di sisi hardware

Berikut catatan yang sekiranya diperhatikan

  • Jika Interface NIC bisa melewatkan bandwidth besar pastikan NIC terpasang di PCIE x16 agar tidak ada bottleneck

Instalasi dan Konfigurasi

sudo apt install bird2 -y

Periksa versi yang terinstall

bird --version

Aktifkan bird agar auto start pada saat startup

sudo systemctl enable --now bird

Basic Configuration

Agar bird dapat mengenali IP yang terpasang di interface sebagai protocol direct lakukan langkah berikut

Beri comment pada baris disabled;

protocol direct {
        disabled;               # Disable by default
        ipv4;                   # Connect to default IPv4 table
        ipv6;                   # ... and to default IPv6 table
}

Sehingga menjadi seperti berikut

protocol direct {
#       disabled;               # Disable by default
        ipv4;                   # Connect to default IPv4 table
        ipv6;                   # ... and to default IPv6 table
}

Agar route yang di set di kernel/diluar bird (misalnya static route dengan ip route add ) dapat dikenali/dibaca oleh bird lakukan langkah berikut

Hapus comment pada baris learn;

protocol kernel {
        ipv4 {                  # Connect protocol to IPv4 table by channel
#             table master4;    # Default IPv4 table is master4
#             import all;       # Import to table, default is import all
              export all;       # Export to protocol. default is export none
        };
#       learn;                  # Learn alien routes from the kernel
#       kernel table 10;        # Kernel table to synchronize with (default: main)
}

Sehingga menjadi seperti berikut

protocol kernel {
        ipv4 {                  # Connect protocol to IPv4 table by channel
#             table master4;    # Default IPv4 table is master4
#             import all;       # Import to table, default is import all
              export all;       # Export to protocol. default is export none
        };
        learn;                  # Learn alien routes from the kernel
#       kernel table 10;        # Kernel table to synchronize with (default: main)
}

Agar bird mendeteksi interface yang up atau down dengan cepat ubah scan time ke waktu yang lebih cepat, defaultnya di bird2 tidak mendefinisikan scan time dan defaultnya adalah 60 detik

protocol device {
}

Tambahkan baris berikut scan time 5; (bird mengecek setiap 5 detik)

Sehingga menjadi seperti berikut

protocol device {
        scan time 5;
}

Contoh Konfigurasi BGP Peer

Contoh BGP peer

protocol bgp RO2 {
        local 12.12.12.1;
        local as 100;
        neighbor 12.12.12.2;
        neighbor as 200;
        ipv4 {
                export all;
                import all;
        };
}

Contoh BGP peer dengan custom filter

protocol bgp RO2 {
        local 12.12.12.1;
        local as 100;
        neighbor 12.12.12.2;
        neighbor as 200;
        ipv4 {
                export filter FILTERNAME_out;
                import filter FILTERNAME_in;
        };
}

Contoh BGP peer Multihop

protocol bgp RO2 {
        local 12.12.12.1;
        local as 100;
        neighbor 12.12.12.2;
        neighbor as 200;
        multihop;
        ipv4 {
                export filter FILTERNAME_out;
                import filter FILTERNAME_in;
        };
}

Contoh BGP peer Route Reflector client

protocol bgp RO2 {
        local 12.12.12.1;
        local as 100;
        neighbor 12.12.12.2;
        neighbor as 200;
        rr client;
        rr cluster id 1.1.1.1;
        ipv4 {
                export filter FILTERNAME_out;
                import filter FILTERNAME_in;
        };
}

Route Filtering

Contoh Mengubah BGP attribute local preference

filter RO2_in {
        if ( net = 2.2.2.2/32 ) then {
                bgp_local_pref = 200;
                accept;
        }
        else accept;
}

Contoh BGP AS path prepend (2x)

filter RO2_out {
        if ( net = 1.1.1.1/32 ) then {
                bgp_path.prepend(100);
                bgp_path.prepend(100);
                accept;
        }
        else reject;
}

100 adalah ASNumber

Contoh BGP menambahkan attribute community

filter RO2_out {
        if ( net = 1.1.1.1/32 ) then {
                bgp_community.add((100,109));
                accept;
        }
        else reject;
}

Contoh BGP menambahkan attribute large community

filter RO2_out {
        if ( net = 1.1.1.1/32 ) then {
                bgp_large_community.add((100,200,109));
                accept;
        }
        else reject;
}

Contoh BGP dengan validasi ROA

## ROA VALIDATION
function is_rpki_invalid() {
  if (net.type = NET_IP4) then {
    return roa_check(rpki4, net, bgp_path.last_nonaggregated) = ROA_INVALID;
  }

  if (net.type = NET_IP6) then {
    return roa_check(rpki6, net, bgp_path.last_nonaggregated) = ROA_INVALID;
  }
}

filter neighbor_in {
        if ( is_rpki_invalid() ) then {
                reject;
        }
        else accept;

Konfigurasi RPKI ROA

# ROA table untuk IPv4 dan IPv6
roa4 table rpki4;
roa6 table rpki6;

# RPKI protocol RTR dari RPKI Cache Server seperti routinator
protocol rpki rpki_roa {
  roa4 { table rpki4; };
  roa6 { table rpki6; };

  remote 10.0.0.1 port 3323;
  retry 30;
}

Template Konfigurasi Utama Bird

define ASN = 65053;
router id 172.16.0.1;

define WARSCLOUDv4 = [
  172.16.0.0/24,
  172.16.1.0/24,
  172.16.2.0/24,
  172.16.3.0/24
];

define WARSCLOUD23v4 = [
  172.16.0.0/23,
  172.16.2.0/23
];

define WARSCLOUDv6 = [
  fd00:dead:bee::/48
];

# INTERNET ROUTABLE PREFIXES length 24
define LOCALv4 = [
  172.16.0.0/24,
  172.16.1.0/24,
  172.16.2.0/24,
  172.16.3.0/24,
  10.10.80.0/20,
  10.10.96.0/20
];


define LOCALv6 = [
  fd00:dead:bee::/48
];

protocol static static4 {
  ipv4;
  route 172.16.0.0/24 reject;
  route 172.16.1.0/24 reject;
  route 172.16.2.0/24 reject;
  route 172.16.3.0/24 reject;
  route 172.16.0.0/23 reject;
  route 172.16.2.0/23 reject;
  route 10.10.80.0/20 reject;
  route 10.10.96.0/20 reject;
}

protocol static static6 {
  ipv6;
  route fd00:dead:bee::/48 reject;
}


##----- PARAMETER -----##

log syslog all;

log "/var/log/bird.log" { debug, trace, info, remote, warning, error, auth, fatal, bug };


timeformat base iso long;
timeformat log iso long;
timeformat protocol iso long;
timeformat route iso long;

protocol device {
  scan time 5;
}

protocol direct {
  ipv4;
  ipv6;
}

protocol kernel {
  scan time 30;
  learn;
  ipv4 {
    import all;
    export filter {
      if source = RTS_DEVICE then reject;
      if source = RTS_STATIC && proto != "static4" then accept;
      if source = RTS_BGP then {
        krt_prefsrc = 172.16.0.1;
        accept;
      }
      else reject;
    };
  };

  merge paths;          # Gabungkan multipath (ECMP)
}

protocol kernel {
  scan time 30;
  learn;
  ipv6 {
    import all;
    export filter {
      if source = RTS_DEVICE then reject;
      if source = RTS_STATIC && proto != "static4" then accept;
      if source = RTS_BGP then {
        krt_prefsrc = 172.16.0.1;
        accept;
      }
      else reject;
    };
  };

  merge paths;          # Gabungkan multipath (ECMP)
}

##----- BLACKHOLING -----##

protocol static null4 {
  ipv4;
  route 192.0.2.1/32 blackhole;
}

protocol static null6 {
  ipv6;
  route 100::1/128 blackhole;
}

##----- RPKI -----##

roa4 table rpki4;
roa6 table rpki6;

#protocol rpki rpki_roa {
#  roa4 { table rpki4; };
#  roa6 { table rpki6; };

#  remote 10.0.0.1 port 3323;
#  retry 30;
#}


##----- FUNCTION -----##

# BLACKHOLE ACTION
function set_blackhole() {
  if (net.type = NET_IP4) then {
    bgp_next_hop = 192.0.2.1;
    print "Added null route for ", net;
  }
  if (net.type = NET_IP6) then {
    bgp_next_hop = 100::1;
    print "Added null route for ", net;
  }
}

# BLACKHOLE DETECTION & ACTION
function process_blackholes() {
  if (((ASN,1,666) ~ bgp_large_community) && ((net.type = NET_IP4 && net.len = 32) || (net.type = NET_IP6 && net.len = 128))) then {
    set_blackhole();
  }
}

# HELPER FUNCTION
function _reject(string reason) {
  reject "REJECTED [", reason, "] pfx ", net, " session ", proto, " path ", bgp_path, " pathlen ", bgp_path.len, " origin ", bgp_path.last;
}

# FILTERING FUNCTION
function honor_graceful_shutdown() {
  if (65535, 0) ~ bgp_community then bgp_local_pref = 0;
}

function reject_local() {
  if (net ~ LOCALv4) then _reject("own prefix");
  if (net ~ LOCALv6) then _reject("own prefix");
}

function reject_long_as_paths() {
  if (bgp_path.len > 100) then _reject("long AS path");
}

function is_rpki_invalid() {
  if (net.type = NET_IP4) then {
    return roa_check(rpki4, net, bgp_path.last_nonaggregated) = ROA_INVALID;
  }

  if (net.type = NET_IP6) then {
    return roa_check(rpki6, net, bgp_path.last_nonaggregated) = ROA_INVALID;
  }
}

function enforce_first_as(int peer_asn) {
  if (bgp_path.first != peer_asn) then _reject("invalid first AS");
}

function enforce_peer_nexthop(ip addr) {
  if (bgp_next_hop != addr) then _reject("nexthop doesn't match neighbor address");
}

function accept_local() {
  if (net ~ LOCALv4) then {
   accept;
  }

  if (net ~ LOCALv6) then {
    accept;
  }
}

function accept_warscloud() {
  if (net = WARSCLOUDv4) then {
   accept;
  }

  if (net = WARSCLOUDv6) then {
    accept;
  }
}

function accept_warscloud23_v4() {
  if (net = WARSCLOUD23v4) then {
    accept;
  }
}

##----- CUSTOM CONFIG -----##

include "manual*.conf";
include "AS*.conf";

Usefull Command

Melihat prefix yang diterima dari BGP neighbor

show route protocol neighbor_name

Melihat prefix yang diterima dari BGP neighbor dengan detail

show route protocol neighbor_name all

Melihat ip dengan tujuan prefix tertentu yang diterima dari neighbor tertentu

show route for 192.168.1.1 protocol neighbor_name all

Melihat prefix yang dikirim ke neighbor tertentu dengan detail

show route export neighbor_name all

Melihat prefix yang diterima namun terfilter

show route filtered

Melihat prefix yang diterima dari neighbor tertentu namun terfilter

show route filtered protocol neighbor_name

Tools atau Konfigurasi Pendukung yang sekiranya berguna (Opsional)

Tools lainnya
mtr
bmon
conntrack
mactelnet-client (disarankan jika terbiasa dengan environment mikrotik)
mactelnet-server (disarankan jika terbiasa dengan environment mikrotik)
ipcalc atau ipcalc-ng
pathvector
softflowd
– ethtool

Script yang berguna untuk menampilkan BGP Summary

#!/bin/bash

birdc show protocols all | awk '
# Fungsi pembantu untuk mengukur panjang teks
function update_max(val, current_max) {
    len = length(val);
    return (len > current_max) ? len : current_max;
}

function save_peer() {
    if (in_bgp) {
        if (channel == "ipv6") {
            v6_count++;
            v6_neigh[v6_count] = neigh;
            v6_asn[v6_count]   = asn;
            v6_proto[v6_count] = proto;
            v6_state[v6_count] = state;
            v6_since[v6_count] = since;
            v6_imp[v6_count]   = imp;
            v6_expt[v6_count]  = expt;

            # Hitung nilai maksimum tiap kolom IPv6
            v6_w_neigh = update_max(neigh, v6_w_neigh);
            v6_w_asn   = update_max(asn, v6_w_asn);
            v6_w_proto = update_max(proto, v6_w_proto);
            v6_w_state = update_max(state, v6_w_state);
            v6_w_since = update_max(since, v6_w_since);
            v6_w_imp   = update_max(imp, v6_w_imp);
            v6_w_expt  = update_max(expt, v6_w_expt);
        } else {
            v4_count++;
            v4_neigh[v4_count] = neigh;
            v4_asn[v4_count]   = asn;
            v4_proto[v4_count] = proto;
            v4_state[v4_count] = state;
            v4_since[v4_count] = since;
            v4_imp[v4_count]   = imp;
            v4_expt[v4_count]  = expt;

            # Hitung nilai maksimum tiap kolom IPv4
            v4_w_neigh = update_max(neigh, v4_w_neigh);
            v4_w_asn   = update_max(asn, v4_w_asn);
            v4_w_proto = update_max(proto, v4_w_proto);
            v4_w_state = update_max(state, v4_w_state);
            v4_w_since = update_max(since, v4_w_since);
            v4_w_imp   = update_max(imp, v4_w_imp);
            v4_w_expt  = update_max(expt, v4_w_expt);
        }
    }
}

BEGIN {
    # Set nilai batas minimal berdasarkan panjang string Header
    v4_w_neigh = 8;  v4_w_asn = 3;  v4_w_proto = 8;  v4_w_state = 5;  v4_w_since = 5;  v4_w_imp = 6;  v4_w_expt = 6;
    v6_w_neigh = 8;  v6_w_asn = 3;  v6_w_proto = 8;  v6_w_state = 5;  v6_w_since = 5;  v6_w_imp = 6;  v6_w_expt = 6;
}

# Parsing output BIRD
/^[^[:space:]]/ {
    save_peer();
    in_bgp = 0;

    if ($2 == "BGP") {
        in_bgp  = 1;
        proto   = $1;
        state   = $NF;
        since   = $5;
        neigh   = "-";
        asn     = "-";
        imp     = 0;
        expt    = 0;
        channel = "ipv4";
    }
    next;
}

in_bgp && $1 == "Neighbor" && $2 == "address:" { neigh = $3; next; }
in_bgp && $1 == "Neighbor" && $2 == "AS:"      { asn = $3; next; }
in_bgp && $1 == "Channel"                       { channel = $2; next; }
in_bgp && $1 == "Routes:"                        { imp = $2; expt = $6; next; }

END {
    save_peer();

    # --- CETAK BLOK IPV4 ---
    if (v4_count > 0) {
        # Format string autofit
        fmt_head = "%-" v4_w_neigh "s  %-" v4_w_asn "s  %-" v4_w_proto "s  %-" v4_w_state "s  %-" v4_w_since "s  %" v4_w_imp "s  %" v4_w_expt "s\n";
        fmt_row  = "%-" v4_w_neigh "s  %-" v4_w_asn "s  %-" v4_w_proto "s  %-" v4_w_state "s  %-" v4_w_since "s  %" v4_w_imp "d  %" v4_w_expt "d\n";

        # Hitung panjang garis pemisah
        line_len = v4_w_neigh + v4_w_asn + v4_w_proto + v4_w_state + v4_w_since + v4_w_imp + v4_w_expt + 12;
        line = ""; for (k = 0; k < line_len; k++) line = line "-";

        print "=== IPv4 BGP SESSIONS ===";
        printf fmt_head, "Neighbor", "ASN", "Protocol", "State", "Since", "Import", "Export";
        print line;
        for (i = 1; i <= v4_count; i++) {
            printf fmt_row, v4_neigh[i], v4_asn[i], v4_proto[i], v4_state[i], v4_since[i], v4_imp[i], v4_expt[i];
        }
        print "";
    }

    # --- CETAK BLOK IPV6 ---
    if (v6_count > 0) {
        # Format string autofit
        fmt_head = "%-" v6_w_neigh "s  %-" v6_w_asn "s  %-" v6_w_proto "s  %-" v6_w_state "s  %-" v6_w_since "s  %" v6_w_imp "s  %" v6_w_expt "s\n";
        fmt_row  = "%-" v6_w_neigh "s  %-" v6_w_asn "s  %-" v6_w_proto "s  %-" v6_w_state "s  %-" v6_w_since "s  %" v6_w_imp "d  %" v6_w_expt "d\n";

        # Hitung panjang garis pemisah
        line_len = v6_w_neigh + v6_w_asn + v6_w_proto + v6_w_state + v6_w_since + v6_w_imp + v6_w_expt + 12;
        line = ""; for (k = 0; k < line_len; k++) line = line "-";

        print "=== IPv6 BGP SESSIONS ===";
        printf fmt_head, "Neighbor", "ASN", "Protocol", "State", "Since", "Import", "Export";
        print line;
        for (i = 1; i <= v6_count; i++) {
            printf fmt_row, v6_neigh[i], v6_asn[i], v6_proto[i], v6_state[i], v6_since[i], v6_imp[i], v6_expt[i];
        }
    }
}
'

Contoh Output:

Neighbor        ASN      Protocol                                 State         Since             Import   Export
--------------------------------------------------------------------------------------------------------------
12.12.12.1      54600   U_AS54600_UPSTREAM_IPT_V4                Established   11:41:22.373           4        2

Script Make IRR filter auto modifikasi dari quantum5/bird-filter

Script:

#!/bin/bash
set -euo pipefail

FILTER_SOURCE=/etc/bird/irr-filters
FILTER_OUTPUT=/etc/bird/filter_irr.conf
PEERINGDB_URL="https://www.peeringdb.com/api/net"

tmpfile="$(mktemp /tmp/bird-filter.XXXXXX)"
cleanup() {
  rm -f "$tmpfile"
}
trap cleanup EXIT

# Fungsi helper untuk mengambil irr_as_set dari PeeringDB
get_as_set_from_peeringdb() {
  local target="$1"
  local asn=""
  
  # Ambil angka ASN dari string (misal: "AS150261" atau "150261" -> "150261")
  asn="$(echo "$target" | grep -oE '[0-9]+' || true)"
  
  if [ -z "$asn" ]; then
    echo ""
    return
  fi

  # Query PeeringDB API
  curl -s "${PEERINGDB_URL}?asn=${asn}" | jq -r '(.data // [])[0].irr_as_set // empty'
}

grep -vE '^#|^$' "$FILTER_SOURCE" | while IFS=$'\t ' read -r -a line; do
  name="${line[0]:-}"
  asset="${line[1]:-}"
  protocol="${line[2]:-}"

  if [ -z "$name" ]; then
    echo "Malformed line found: missing name" 1>&2
    continue
  fi

  # =========================================================
  # LOGIKA MANUALLY VS AUTOMATIC (PEERINGDB)
  # =========================================================
  # Jika kolom asset kosong OR berisi 'AUTO' OR 'PEERINGDB',
  # lakukan query otomatis ke PeeringDB.
  if [ -z "$asset" ] || [ "$asset" = "AUTO" ] || [ "$asset" = "PEERINGDB" ]; then
    echo "Info: Querying PeeringDB for $name..." 1>&2
    auto_asset="$(get_as_set_from_peeringdb "$name")"
    
    if [ -n "$auto_asset" ]; then
      asset="$auto_asset"
      echo "Info: Found AS-SET '$asset' for $name on PeeringDB" 1>&2
    else
      # Jika di PeeringDB kosong, fallback menggunakan ASN itu sendiri (misal: AS150261)
      asset="$name"
      echo "Warning: No IRR AS-SET found on PeeringDB for $name. Falling back to '$asset'" 1>&2
    fi
  fi
  # =========================================================

  # Generate prefix-list BIRD menggunakan bgpq4
  [ "$protocol" != v6 ] && bgpq4 -4Ab -m24 "$asset" -l "define IRR_${name}_V4"
  [ "$protocol" != v4 ] && bgpq4 -6Ab -m48 "$asset" -l "define IRR_${name}_V6"
  bgpq4 -tb "$asset" -l "define IRR_${name}_ASN"

done > "$tmpfile"

mv "$tmpfile" "$FILTER_OUTPUT"
chmod a+r "$FILTER_OUTPUT"

Contoh Input:

# FORMAT: <NAME_ALIAS/ASN>  <AS-SET / MODE>  <PROTOCOL_OPTIONAL>
# ----------------------------------------------------------------

# 1. CARA MANUAL (Sebutkan AS-SET-nya secara eksplisit)
CUSTOMERX       RADB::AS-NOTNET               v4
CLIENT_A        AS139281:AS-CUSTOMERS   both

# 2. CARA OTOMATIS (Script cari sendiri AS-SET nya di PeeringDB)
AS65000          AUTO                    v4
AS65001          PEERINGDB               both
AS15169          AUTO                    v4

Sumber/Referensi:

https://t.me/IPv6_Indonesia/104851/245315