BGP Bird – przydatne filtry #1

Garść przydatnych filtrów do daemona BGP Bird, które pomogą Wam lepiej sterować ruchem przychodzącym.

Zaczniemy od czegoś prostego, czyli uniwersalny filtr dla importowanych prefixów, który można wykorzystać dla większości sesji BGP:

function bogon_network()
 {
    return net ~ [ 169.254.0.0/16+, 172.16.0.0/12+, 192.168.0.0/16+, 10.0.0.0/8+, 240.0.0.0/4+, 224.0.0.0/4+, 0.0.0.0/32- ];
 }
 function my_network()
 {
     return net ~ [ X.X.X.0/24+ ];
 }

 filter DEFAULT_IN {
  if bogon_network() then reject;
  if my_network() then reject;
  if (net.len < 8) || (net.len > 24) then reject;
  if ( bgp_path.len > 50 ) then reject;
  accept;
 }

Powyższy filtr wykorzystuje dwie funkcje. Pierwsza bogon_network, jak nazwa wskazuje zawiera sieci bogon. Druga my_network zawiera nasze prefixy. Znak „+/-” za prefixem oznacza sieci mniejsze lub większe od wskazanego prefixu (odpowiednik le i ge z Cisco). Nasz filtr DEFAULT_IN działa następująco:
– odrzuca prefixy z funkcji bogon_network
– odrzuca prefixy z funkcji my_network
– odrzuca prefixy z maską spoza zakresu /8 do /24
– odrzuca prefixy z dłuższym as-path niż 50 (kiedyś takie rozgłoszenie potrafiło wywalić proces quagga).
– akceptuje całą resztę

Powyższy przykład jak wspomniałem nadaje się jako szablon dla większości sesji BGP z zewnętrznymi peerami. Można go sobie jednak zmodyfikować pod konkretnego peera, poniżej przykład dla EPIX Open Peering:

filter WAR_EPIX_IN {
  if bogon_network() then reject;
  if my_network() then reject;
  if (net.len < 8) || (net.len > 32) then reject;
  if ( bgp_path.len > 50 ) then reject;
  if  ((48850,666) ~ bgp_community ) then  {
         dest = RTD_BLACKHOLE;
         preference = 666;
         accept;
  }
  accept;
 }

Zmieniłem tutaj dwie rzeczy. Poszerzyłem zakres akceptowanych prefixów tak by akceptować mniejsze niż /24, aż do /32. Dlaczego? Po pierwsze w open peeringach zdarzają się prefixy np. /25, a po drugie chcę wykorzystać fakt, że EPIX rozgłasza prefixy z community blackhole do wszystkich uczestników. I to jest właśnie druga zmiana. Jak widać w ostatnim warunku if, wskazałem aby wszystkie otrzymane prefixy z community 48850:666 (EPIX BH) oznaczyć atrybutem RTD_BLACKHOLE i podnieść im preferencje, tak by nie były osiągalne dla klientów w mojej sieci. Efekt poniżej:

bird> show route for 185.9.124.184
 185.9.124.184/32   blackhole [WAR_EPIX_RS1 2021-03-15 00:33:15 from 89.46.144.11] * (666) [AS12741?]
                    blackhole WAR_EPIX_RS2 2021-03-15 00:33:15 from 89.46.144.12 [AS12741?]

A teraz kilka przykładów, które pozwolą nam podbić preferencje dla konkretnych prefixów (bez zmiany dla pozostałych prefixów odbieranych od tego peera) Zacznijmy od najprostszej metody, czyli wskazania prefixu któremu chcemy zmienić preferencję. Posłużę się domyślnym filtrem:

filter DEFAULT_IN {
   if bogon_network() then reject;
   if my_network() then reject;
   if (net.len < 8) || (net.len > 24) then reject;
   if ( bgp_path.len > 50 ) then reject;
   if net = 8.8.8.0/24 then bgp_local_pref=600;
   accept;
  }

Ostatni warunek powoduje, że dla prefixu 8.8.8.0/24 podbijamy bgp local preference do 600.

Powyższa metoda nie zawsze będzie wystarczająca. Dużo bardziej elastyczną metodą jest filtrowanie z wykorzystaniem AS-Path. Możemy sobie np filtrować czy zmienić preferencje prefixów odbieranych od konkretnego ASN. Np:

filter DEFAULT_IN {
    if bogon_network() then reject;
    if my_network() then reject;
    if (net.len < 8) || (net.len > 24) then reject;
    if ( bgp_path.len > 50 ) then reject;
    if bgp_path.last = 15169 then bgp_local_pref=600;
    accept;
   }

Czyli wszystkie prefixy których AS-Path kończy się AS15169, będą miały zmieniony bgp local preference na 600. Możemy też odrzucać takie prefixy, wtedy po then podajemy reject. Powyższy przykład można jeszcze zapisać nieco inaczej i zamiast „bgp_path.last” można użyć „(bgp_path ~ [= * 15169 =])”. Inny przykład:

filter DEFAULT_IN {
     if bogon_network() then reject;
     if my_network() then reject;
     if (net.len < 8) || (net.len > 24) then reject;
     if ( bgp_path.len > 50 ) then reject;
     if (bgp_path ~ [= * 12741 * =]) then reject;
     accept;
    }

W tym wypadku filtrujemy wszystkie prefixy które w ścieżce mają AS12741.

Na koniec filtr przychodzący który wykorzystuje na sesjach z Cymru (pisałem o nich na blogu) albo z własnym systemem antyddos:

filter CYMRU_IN {
  dest = RTD_BLACKHOLE;
  preference = 666;
  accept;
 }

Po prostu wszystkie odbierane prefixy dostają atrybut RTD_BLACKHOLE.

Mam nadzieję, że te kilka przykładów będą dla Was pomocne. W kolejnym wpisie zajmę się filtrami typu export.