img.png

Всем привет!

В этой небольшой статье, хочу продолжить делиться теми инструкциями, которые появляются при использовании оборудования
от B4COM.

До этого уже писал что-то общее про вендора - Базовое описание

И была одна статейка по настройке Radius - Настройка RADIUS на B4COM 41хх в связке с Cisco ISE

P.S. если вам кажется данное полезным и интересным, то буду рад обратной связи с идеями на тему статей.

Плоскость управления - что это и зачем её защищать?

Как вы все прекрасно знаете, у нас существует три плоскости взаимодействия - Data Plane, Control Plane и Management Plane.

Конкретно в этой статье, хочу остановиться только на Control Plane или плоскости управления.

В интернете есть миллион статей на эту тему, поэтому не хочу особенно повторяться, напишу коротко.

В общем, Control Plane, или плоскость управления - это некоторый уровень, слой или абстракция внутри любого оборудования (да, не только сетевики используют термин), которая занимается изучением и анализом разных параметров и свойств, которые в
дальнейшем требуется для корректной работы системы.

Например, всеми любимый K8s тоже имеет свой Control Plane - это собственно та часть, через которую вы управляете кластерами, мониторите их состояние и т.д.

Если говорить про сеть и оборудование вокруг, то для нас, сетевиков, Control Plane - это уровень где работают протоколы маршрутизации, механизмы заполнения таблиц, всякие служебные протоколы типа ND или ARP, ну и так далее.

Вот тут почитайте в общем:

Ок, что это примерно понятно. Остаётся вопрос зачем нам это защищать. Ну на самом деле ответ лежит на поверхности, очевидно что защита нужна во благо качественной работы того самого Control Plane.

Это может быть защита от злоумышленников, или защита от каких-то либо ошибок конфигурации других устройств, чтобы переживать аварию, либо просто мы не хотим тратить ресурс на обработку какого-то протокола, который у нас и не используется вовсе.

Исходя из особенностей работы Control Plane, возникает пара вариантов.

Защита на уровне hardware

Тут собственно подразумевается фильтрация на ASICе. Т.к. мы говорим про B4COM, то у оборудования есть сразу вложенный механизм распределения по очередям на аппаратном уровне, которым вы можете управлять.

Все очереди заранее настроены и распределены по протоколам. Посмотреть текущее состояние можно следующими командами

show cpu-queue details - все очереди и настройки

switch#show cpu-queue details
* - Can not configure the parameter
Cpu queue                  Rate In PPS                     Monitor Status            Lossy Status        
Name          Configured  Default   Max Rate Allowed  Configured    Default     Configured  Default     
===========   ==========  =======   ================  ===========   ==========  =========== ==========  
best-effort     -            2113          2113           -       * no-monitor      -        * lossy        
ipmc-miss       -            2113          2113           -       * no-monitor      -        * lossy        
l3-miss         -            211           211            -       * no-monitor      -        * lossy        
sflow           -            32000         100000         -         monitor         -        * lossy        
bgp             -            1500          1500           -         monitor         -          lossless     
vrrp            -            1024          1024           -         monitor         -          lossless     
ldp-rsvp        -            500           500            -         monitor         -          lossless     
rip             -            500           500            -         monitor         -          lossless     
ospf            -            2000          2000           -         monitor         -          lossless     
dhcp            -            100           2048           -         no-monitor      -          lossy        
nd              -            6000          6000           -         monitor         -          lossless     
mpls            -            500           500            -         no-monitor      -          lossy        
pim             -            4000          4000           -       * no-monitor      -        * lossy        
arp             -            6000          6000           -         monitor         -          lossless     
igmp            -            4000          4000           -       * no-monitor      -        * lossy        
bpdu            -            10000         10000          -         monitor         -          lossless     
ccm             -            1000          1000           -         no-monitor      -          lossy        
bfd             -            2000          2000           -         no-monitor      -          lossy        
ptp             -            1000          1000           -         no-monitor      -          lossy        
isis            -            500           1000           -         monitor         -          lossless     
trill-isis      -            1000          1000           -         monitor         -          lossless     
acl             -            200           1000           -       * no-monitor      -        * lossy        
vxlan           -            500           6000           -         monitor         -          lossy        
daivm           -            100           500            -         no-monitor      -          lossy        
switch#  

show interface cpu counters queue-stats - счетчики пакетов по очередям в сторону CPU и дропы

switch#show interface cpu counters queue-stats
E - Egress, I - Ingress, Q-Size is in bytes
+--------------------+--------+-----------------+-------------------+-----------------+-------------------+
|   Queue/Class-map  | Q-Size |     Tx pkts     |     Tx bytes      |  Dropped pkts   |   Dropped bytes   |
+--------------------+--------+-----------------+-------------------+-----------------+-------------------+
best-effort       (E) 0        0                 0                   0                 0                  
bgp               (E) 0        0                 0                   0                 0                  
nd                (E) 0        0                 0                   0                 0                  
arp               (E) 0        0                 0                   0                 0                  
bpdu              (E) 0        0                 0                   0                 0                  
hw-bfd            (E) 0        0                 0                   0                 0                  

switch#  

Добавить протокол, либо изменить очередь невозможно, не поддерживается оборудованием, но можно управлять следующими параметрами:

lossless - отбрасывать пакеты на входящем интерфейсе (работает механизм backpressure).
Это по сути shaper. Складывает всё в буфер входящего интерфейса и ничего не отбрасывает пока там есть место.

lossy - отбрасывать пакеты при превышении непосредственно на самой очереди. 
Это policer, т.е. срезает всё что выше указанного порога.

monitor - логирование пакетов, которые отбрасываются

no-monitor - очевидно, что выключение логирования пакетов, которые отбрасываются

rate - ограничение по pps, триггер на который будут срабатывать собственно все параметры выше. 

Делается вот тут, покажу на примере sflow:

switch#conf t
switch(config)#cpu-queue bgp ?
 lossless    Configure cpu queue as lossless
 lossy       Configure cpu queue as lossy
 monitor     monitor cpu queue usage
 no-monitor  do not monitor cpu queue usage
 rate        Set cpu queue rate

И выставляете требуемое значение для rate, либо меняете lossless (shaper) на lossy (policer).

С аппаратным разобрались, пойдём посмотрим теперь на второй вариант управления трафиком в сторону CPU - софтовый.

Защита на уровне software

Тут начинается русское поле экспериментов территория полученная опытным путём.

Ни для кого ни секрет, что под капотом у нас всё тот же Linux, а именно Debian. Отсюда можно сделать вывод, что вся фильтрация будет выполняться средствами iptables. Т.к. мы говорим про трафик, который идёт внутрь коммутатора и не является транзитным, то соответственно со стороны iptables - это будет цепочка INPUT. Выходит, если мы сможем ей управлять, то задача по фильтрации данного трафика будет решена.

Собственно, тут есть 2 способа:

  1. Нативно идти в Linux Shell и там править iptables, в целом способ реальный, но удобным его назвать сложно. Поэтому давайте сразу пропустим.
  2. Использовать вложенную фичу, управляя iptables через интерфейс loopback.

Работает это следующий образом. При использовании ACL на интерфейс loopback, мы автоматически программируем правила для iptables. То есть, для этого нам нужно:

  • создать ACL
  • применить его на loopback интерфейс в направлении IN (мы ведь хотим трафик идущий в голову срезать).
  • всё.

Ок, давайте попробуем.

Автоматически, у нас создаётся всегда интерфейс lo, вот его мы и будем использовать:

interface lo  
 ip address 127.0.0.1/8  
 ipv6 address ::1/128  
!  
switch# 

Предварительно, проверяем что у нас в текущих правилах iptables, для этого проваливаемся в shell и смотрим:

start-shell
su -
####
root@switch:~# iptables -L  
Chain INPUT (policy ACCEPT)  
target     prot opt source               destination           
  
Chain FORWARD (policy ACCEPT)  
target     prot opt source               destination           
  
Chain OUTPUT (policy ACCEPT)  
target     prot opt source               destination           
root@switch:~#   

Ок, пусто. Всё разрешено.

Создадим простой ACL для фильтрации telnet:

ip access-list acl_copp_in  
 5 permit any 127.0.0.0 0.255.255.255 any  ### ЭТО ВАЖНО!!!
 10 deny tcp any any eq telnet
 
Внимательный читатель спросит, а зачем тут permit на 127.0.0.0/8. 
Ответ следующий - ТАК НАДО. 
Без него ломаются многие внутренние сервисы, перестаёт работать NTP, SNMP и т.д. 
Выявлено опытным путём и это обязательный к разрешению параметр, который должен стоят первым, во избежание ошибки :)

Далее повесим его на наш лупбек:

interface lo  
 ip address 127.0.0.1/8 
 ipv6 address ::1/128  
 ip access-group acl_copp_in in  
!  
switch# 

Идём в шел, там смотрим что у нас с iptables и убеждаемся, что действительно наше правило попало в цепочку INPUT.

start-shell
su -
####
root@switch:~# iptables -L  
Chain INPUT (policy ACCEPT)  
target     prot opt source               destination           
ACCEPT     all  --  anywhere             switch          
ACCEPT     all  --  loopback/8           anywhere              
DROP       tcp  --  anywhere             anywhere             tcp dpt:telnet
  
Chain FORWARD (policy ACCEPT)  
target     prot opt source               destination           
  
Chain OUTPUT (policy ACCEPT)  
target     prot opt source               destination           
root@switch:~# 

Обратите внимание, мы повесили ACL на автоматически созданный loopback, который находится в GRT (дефолтной таблице маршрутизации). Собственно фильтрация и будет проводиться ровно тут, и если у нас трафик идёт внутри какого-то VRF, то фильтрация его не коснётся и он достигнет цели. Поэтому, если мы хотим фильтровать внутри какого-то VRFа, то нужно добавить точно такой же ACL, но уже для loopback внутри этого VRF. Благо они автоматически создаются и остаётся его только туда привязать. ACL при этом можно оставить тот же самый, создавать отдельный смысла нет.

Давайте попробуем.

Для теста, создал вот такой VRF - copp_test

switch#sh run vrf  test_copp  
!  
ip vrf test_copp  
!  
switch#  
switch#sh run int lo.test_copp  
!  
interface lo.test_copp  
!  

Пойдём проверим в шел. Как вы знаете VRF = namespace в линукс, поэтому нужно учитывать этот момент и смотреть таблицу iptables для нужного нам. Как узнать какой именно нам нужен? Для этого сначала делаем вот такую команду:

switch#  
switch#sh ip vrf   
VRF management, VRF ID: 1, FIB ID 1  
 Router ID: 1.1.1.1 (automatic)  
Interfaces:  
  eth0  
  lo.management  
!  
VRF test_copp, VRF ID: 2, FIB ID 2  
 Router ID is not set  
Interfaces:  
  lo.test_copp  
!  
Total Number of configured IP VRF's: 2  
Total Number of all VRF's: 3  
  
Name                               Default RD  
management                         not set               
test_copp                          not set               
switch#  

Благодаря ей, мы получаем информацию о том, какой номер FIB ID, у нашего VRF.

VRF test_copp, VRF ID: 2, FIB ID 2

Теперь идём в шел и смотрим список всех неймспейсов:

start-shell
su -
####
ip netns list
root@switch:~# ip netns list
zebosfib2 (id: 1)
zebosfib1 (id: 0)
zebosfib0

Ок, видим, что тут есть namespace с именем zebosfib2, что соответствует тому номеру, который мы узнали чуть раньше. Смотрим что у него в настройках iptables:

root@switch:~# ip netns exec zebosfib2 iptables -L  
Chain INPUT (policy ACCEPT)  
target     prot opt source               destination           
  
Chain FORWARD (policy ACCEPT)  
target     prot opt source               destination           
  
Chain OUTPUT (policy ACCEPT)  
target     prot opt source               destination           
root@switch:~#   
root@switch:~#   

Пусто, всё разрешено. Ну ожидаемо, мы ведь ничего и не фильтровали.

Ок, делаем аналогично предыдущему и вешаем ACL на автоматический созданный loopback, для этого VRF.

switch#sh run int lo.test_copp  
!  
interface lo.test_copp  
 ip vrf forwarding test_copp  
 ip access-group acl_copp_in in  
!  
switch#  

Проверяем iptables:

root@switch:~#   
root@switch:~# ip netns exec zebosfib2 iptables -L  
Chain INPUT (policy ACCEPT)  
target     prot opt source               destination           
ACCEPT     all  --  anywhere             localhost             
ACCEPT     all  --  loopback/8           anywhere              
DROP       tcp  --  anywhere             anywhere             tcp dpt:telnet  
  
Chain FORWARD (policy ACCEPT)  
target     prot opt source               destination           
  
Chain OUTPUT (policy ACCEPT)  
target     prot opt source               destination           
root@switch:~#   
root@switch:~#   

Вуаля, наш фильтр применился и сюда.

А дальше остаётся только сделать корректные правила, описать их в ACL и применить. Вот и всё. CPU будет защищён.

Я бы рекомендовал тут действовать следующим путём, допустим вы хотите выставить фильтры для SSH. Вы заранее знаете список тех адресов, которым можно ходить и формируете ACL следующего вида:

ip access-list test_copp
 5 permit any 127.0.0.0 0.255.255.255 any        ### НЕ ЗАБЫВАЕМ! 
 10 permit tcp ALOWED_NETWORK/HOST any eq ssh    ### разрешаем доступ отсюда
 20 permit tcp ALOWED_NETWORK/HOST any eq ssh    ### и отсюда

но, в конце разрешенного списка, с каким-то отступом делаете deny any any для конкретного протокола, таким образом вы его запрещаете для всех, кроме вышеописанных, получается что-то типа:

ip access-list test_copp
 5 permit any 127.0.0.0 0.255.255.255 any        
 10 permit tcp ALOWED_NETWORK/HOST any eq ssh
 20 permit tcp ALOWED_NETWORK/HOST any eq ssh
 50 deny tcp any any eq ssh                      ### Запрещаем всё остальное для SSH

Ну и так далее для остальных протоколов, допустим используем BGP, SNMP, NTP, SSH и Syslog получается что-то типа:

ip access-list test_copp
 5 permit any 127.0.0.0 0.255.255.255 any        
 10 permit tcp ALOWED_NETWORK/HOST any eq ssh
 20 permit tcp ALOWED_NETWORK/HOST any eq ssh
 50 deny tcp any any eq ssh
 60 permit udp host ALOWED_NETWORK/HOST any eq snmp
 70 permit udp host ALOWED_NETWORK/HOST any eq snmp
 100 deny udp any any eq snmp
 110 permit tcp ALOWED_NETWORK/HOST any eq bgp
 120 permit tcp ALOWED_NETWORK/HOST any eq bgp
 150 deny tcp any any eq bgp
 160 permit udp host ALOWED_NETWORK/HOST any eq ntp
 170 permit udp host ALOWED_NETWORK/HOST any eq ntp
 200 deny udp any any eq ntp
 210 permit udp host ALOWED_NETWORK/HOST any eq syslog
 220 permit udp host ALOWED_NETWORK/HOST any eq syslog
 250 deny udp any any eq syslog

т.к. мы хотим эти протоколы закрыть, а всё остальное будто бы и не мешает, то в конце повесим explicit permit, т.е. permit any any.
В итоге получаем вот такой ACL:

ip access-list test_copp
 5 permit any 127.0.0.0 0.255.255.255 any        
 10 permit tcp ALOWED_NETWORK/HOST any eq ssh
 20 permit tcp ALOWED_NETWORK/HOST any eq ssh
 50 deny tcp any any eq ssh
 60 permit udp host ALOWED_NETWORK/HOST any eq snmp
 70 permit udp host ALOWED_NETWORK/HOST any eq snmp
 100 deny udp any any eq snmp
 110 permit tcp ALOWED_NETWORK/HOST any eq bgp
 120 permit tcp ALOWED_NETWORK/HOST any eq bgp
 150 deny tcp any any eq bgp
 160 permit udp host ALOWED_NETWORK/HOST any eq ntp
 170 permit udp host ALOWED_NETWORK/HOST any eq ntp
 200 deny udp any any eq ntp
 210 permit udp host ALOWED_NETWORK/HOST any eq syslog
 220 permit udp host ALOWED_NETWORK/HOST any eq syslog
 250 deny udp any any eq syslog
 999 permit any any any

Таким образом, мы защищаем наш CPU от попыток взлома по тем протоколам, которыми пользуемся, но и не ограничиваем остальное. Если же вы хотите отключить всё, то тут вам придётся более тщательно поработать над своим ACL, перед тем как его применить, а то сами знаете как оно бывает :)

img.png


Заключение

Вот и всё что хотел сказать, надеюсь было полезно.

Повторюсь - хотите больше таких или других статей, пишите фидбек, с ним гораздо проще понимать что именно вам интересно.

Не забывайте поделиться с коллегами, друзьями и тем, кто по вашему мнению будет заинтересован. Таким образом вы окажете поддержку мне и выразите свою благодарность.

Спасибо за внимание!

Подписывайтесь на канал!