Архитектура сети на базе Cisco для оперативного включения защиты от DDoS

в 3:37, , рубрики: BGP, Cisco, ddos, информационная безопасность, метки: , ,

Дано:
• Крупная корпоративная сеть на базе разнообразных железок Cisco с развернутым MPLS/VPN.
• PI блок адресов /22, в котором есть незанятая сеть /24, BGP пиринг с провайдерами.
• Несколько доступных из интернета ресурсов, падение которых несет либо репутационные, либо прямые финансовые потери. Соответственно, есть риск атаки на них, а каналы в интернет хоть и широкие, но вовсе не резиновые. В нормальной ситуации трафик от/до этих ресурсов копеечный, несколько мегабит.
• Некий очень ленивый сетевик, который не хочет, чтобы его будили посреди ночи из-за каких-то там атак.

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

Disclaimer. Все дальнейшее содержит массу искажений по разнообразным деталям, но сама архитектура осталась неизменной. Я буду много касаться вопроса настройки маршрутизации, и совсем не буду рассматривать защиту management plane сетевого оборудования от приставаний со стороны угнанного кем-то дырявого вебсервера.

Для начала, необходимо ответить на следующий вопрос: каким образом защищаться?
• Любые механизмы, реализуемые внутри сети, могут помочь от исчерпания ресурсов сервера, но каналы в интернет они не спасут. 10гб/с UDP флуд – и мы отрезаны от внешних сетей.
• BGP blackholing и иже с ним? Ну да, каналы спасены, вот только цель атаки выполнена – интернет-ресурсы лежат. Не годится.
• Заказать услугу защиты от DDoS у провайдера? Не вопрос. Но: качество фильтрации у них обычно не самое лучшее, да и будут проблемы с BGP multihoming’ом. Любой трафик, ходящий через канал провайдера с включенным antiDDOS’ом, должен быть симметричен. Сейчас у нас примерно равномерная загрузка всех интернет-каналов, а придется либо бросить вообще всё на один канал (нагрузка станет высокой даже без всяких атак, придется увеличивать его емкость), либо оставить на нем только защищаемые ресурсы (нагрузка станет почти нулевая). Некрасиво. Мне очень хочется, чтобы защита от DDoS никак не влияла на работу других ресурсов и периметров.
• Использование услуг сторонней организации. Они отслеживают нагрузку на сервера, в случае обнаружения атаки щелкают пальцами, и трафик от/до наших серверов начинает ходить через них. Под «щелчком» может пониматься либо изменение DNS записи (очень медленно, да и вообще убого), либо анонс через них защищаемой сети (быстро и безотказно, но требует предварительной подготовки).

Мы остановились на последнем варианте.

В ходе совещания с представителями организации, предоставляющей защиту от DDoS атак (все ее знают, не хочется их пиарить, потому назовем их «Защитниками») выяснилось, что у нас с ними нет общих точек присутствия, потому придется поднимать BGP пиринг через GRE туннели по интернету, и через них принимать/отдавать трафик защищаемых ресурсов. На этом этапе я сначала немного обалдел: «Так мы же и защищаем интернет-каналы. Если их завалили, то мы, получается, остаемся и без защиты?». Оказалось, своя логика в такой архитектуре есть. Атака не выйдет на максимальную мощность мгновенно, минут 5-10 от начала атаки до блэкаута у нас будет, да и в любом случае ничто не мешает Защитникам создать анонс на сеть и без нашего участия.

Сеть, которую мы им анонсируем, не может быть меньше, чем /24, иначе магистральщики легко могут ее прибить.

Ах да, чуть не забыл. Мы предоставляем Защитникам сервер, расположенной внутри нашей сети. Они ставят на него свои анализаторы, а мы средствами SPANа сливаем на один из его интерфейсов копию всего трафика защищаемых сервисов. То есть они будут отвечать за обнаружение атак.

Итак, переходим к самой интересной части, а именно: надо все настроить так, чтобы переключение осуществлялось лишь силами Защитников, после устного «ok» со стороны сотрудника службы безопасности, и совсем без участия сетевиков. А еще это переключение не должно задеть другие внешние и внутренние ресурсы.

Вот принципиальная топология сети. На стыке между всеми периметрами размещен файрвол Cisco ASA (занимается NATом и фильтрацией трафика по ACL), имеются пограничные маршрутизаторы, между ними и файрволом L2 свитч.
Архитектура сети на базе Cisco для оперативного включения защиты от DDoS

Первый вопрос: откуда тянуть GRE туннели до Защитников? Казалось бы, самый логичный ответ – «через пограничные BGP маршрутизаторы». Но мне этот вариант не нравится. Ведь в туннели нужно будет пускать только защищаемый трафик, все остальные пакеты должны будут лететь по старинке. Надо сделать так, чтобы для разных отправителей пакетов действовали разные правила маршрутизации. MPLS, разумеется, не тянется до пограничных маршрутизаторов, потому остается только вариант с Policy-based routing. Я к нему отношусь примерно так же, как мои бывшие преподаватели по разного рода программированиям относились к оператору «GOTO», то есть в моей сети никакого PBR не будет.

ASA тоже не отличается избирательностью по отношению к отправителям пакетов, потому получается, что маршруты должны меняться где-то внутри сети. Следовательно, нужно будет создать отдельный VRF. И понадобится какая-то отдельная железка, один из интерфейсов которой мы высадим аккурат между файрволом и пограничными маршрутизаторами (не высовывать же ядро сети наружу?). От нее не потребуется какого-либо инспектирования трафика выше L4 (Защитники этим займутся), да и на L4 ничего кроме аксесс-листов не нужно. Какое устройство поддерживает BGP, GRE и сможет прокачать через себя ровно столько трафика, сколько ему дать, и при этом стоит недорого? Правильно, идем на склад и берем лишний свитч Cisco Catalyst 3750 на 24 медных гигабитных порта и 4 SFPшных аплинка.

Размещаем его в сети, и планируем, как пойдет трафик в нормальной ситуации (зеленый цвет) и под атакой (красный).
Архитектура сети на базе Cisco для оперативного включения защиты от DDoS

У внимательного читателя сразу возникнет вопрос: а кто будет NATить пакеты до серверов и обратно? Ведь 3750-й каталист не поддерживает эту фичу… Ответ: «никто». Разве кто-то говорит, что NAT обязательно требуется? Что-то мешает сразу назначить внешний адрес интерфейсу сервера? Ведь в таком подходе есть одно радикальное преимущество: при мощном SYN флуде нашей ASA может сильно поплохеть, а, сняв с нее задачу NATа, мы здорово экономим ее ресурсы. Ну и вдобавок, после переключения в режим защиты трафик до атакуемых серверов вообще не проходит через ASA – а ведь существенную долю в нем может составлять мусор.

Кстати о ресурсах. Отключаем к чертовой бабушке поднятый на пограничных маршрутизаторах Netflow. Да, сейчас у них ЦПУ в пике загружен от силы до 10%, но они легко могут скопытиться от банальных 100мб/с SYN пакетов, надо беречь их силы.

Как же все-таки будет осуществляться переключение? У нас есть, допустим, PI AS 11111 с сетью 198.51.100.0/22. В ней, как уже говорилось выше, свободна одна сеть /24, пусть это будет 198.51.103.0/24. В час «Ч» Защитники выпускают наружу принимаемый от нас анонс на 198.51.103.0/24, а нам выдают маршрут на 0.0.0.0/0 через один из GRE туннелей. Или через несколько – тогда MED скажет, каким пользоваться.

Поехали настраивать.

Сначала sw-ddos:

Sw-ddos(config)#

!Делаем интерфейс до Core:
interface GigabitEthernet1/0/25
 no switchport
 ip address 169.254.0.2 255.255.255.252

!готовим входящий ACL для интерфейса, по которому должен ходить только GRE трафик:
ip access-list extended fromoutside_phy
 permit gre host 100.0.0.1 host 198.51.101.10
 permit gre host 100.1.0.1 host 198.51.101.10
 permit gre host 100.2.0.1 host 198.51.101.10
 permit gre host 100.3.0.1 host 198.51.101.10

!Сам интерфейс:
Interface GigabitEthernet1/0/24
 no switchport
 ip address 198.51.101.10 255.255.255.0
 ip access-group fromoutside_phy in 

!Входящий ACL для туннелей:
ip access-list extended fromoutside
 permit tcp host 10.10.0.1 host 10.10.0.2 eq bgp
 permit tcp host 10.10.0.1 eq bgp host 10.10.0.2
 permit tcp host 10.10.0.5 host 10.10.0.6 eq bgp
 permit tcp host 10.10.0.5 eq bgp host 10.10.0.6
 permit tcp host 10.10.0.9 host 10.10.0.10 eq bgp
 permit tcp host 10.10.0.9 eq bgp host 10.10.0.10
 permit tcp host 10.10.0.13 host 10.10.0.14 eq bgp
 permit tcp host 10.10.0.13 eq bgp host 10.10.0.14
 permit tcp any host 198.51.103.5 eq www

 
 !Сами туннели:
interface Tunnel1
 ip address 10.10.0.2 255.255.255.252
 ip access-group fromoutside in
 tunnel source GigabitEthernet1/0/24
 tunnel destination 100.0.0.1
interface Tunnel2
 ip address 10.10.0.6 255.255.255.252
 ip access-group fromoutside in
 tunnel source GigabitEthernet1/0/24
 tunnel destination 100.1.0.1
interface Tunnel3
 ip address 10.10.0.10 255.255.255.252
 ip access-group fromoutside in
 tunnel source GigabitEthernet1/0/24
 tunnel destination 100.2.0.1
interface Tunnel4
 ip address 10.10.0.14 255.255.255.252
 ip access-group fromoutside in
 tunnel source GigabitEthernet1/0/24
 tunnel destination 100.3.0.1

!Чуть не забыл маршруты до GRE ендпоинтов со стороны Защитников – пусть будет статика, указывающая на пограничный маршрутизатор:
ip route 100.0.0.1 255.255.255.255 198.51.101.1
ip route 100.1.0.1 255.255.255.255 198.51.101.1
ip route 100.2.0.1 255.255.255.255 198.51.101.1
ip route 100.3.0.1 255.255.255.255 198.51.101.1

!Ну и лупбек – чтобы достучаться до этого свитча:
interface Loopback0
 ip address 192.168.0.15 255.255.255.255

!Роут-мапы для BGP, фильтрующие обмен префиксами с Защитниками:
ip prefix-list from_Def seq 5 permit 0.0.0.0/0
ip prefix-list to_Def seq 5 permit 198.51.103.0/24
!(ибо мы хотим принимать от них только дефолтный маршрут, а отдавать – только целевую /24 сеть)

route-map from_Def permit 10
 match ip address prefix-list from_Def
route-map to_Def permit 10
 match ip address prefix-list to_Def

!А вот дальше уже роут-мапы для внутреннего пиринга с ядром сети
route-map from_Inside deny 10
 match ip address prefix-list from_Def
!режем на корню дефолтный маршрут

route-map from_Inside permit 20
!остальное разрешаем

!Сам BGP (в той же AS, что и пограничные маршрутизаторы):
router bgp 11111
 no auto-summary
 bgp log-neighbor-changes

!Защитники могут MEDом указывать нам, через какой туннель идти, потому:
 bgp deterministic-med
 bgp bestpath med missing-as-worst

!анонсируем лупбек
 network 192.168.0.15 mask 255.255.255.255

!Создаем summary на защищаемую сеть – у нас ведь будет несколько сетей из доступного блока /24
 aggregate-address 198.51.103.0 255.255.255.0 summary-only

!Сам пиринг:
 neighbor DEF peer-group
 neighbor DEF remote-as 2222
 neighbor DEF timers 20 60
 neighbor DEF soft-reconfiguration inbound
 neighbor DEF route-map from_DEF in
 neighbor DEF route-map to_DEF out
 neighbor INSIDE peer-group
 neighbor INSIDE remote-as 65000
 neighbor INSIDE soft-reconfiguration inbound
 neighbor INSIDE route-map from_Inside in
 neighbor 10.10.0.1 peer-group DEF
 neighbor 10.10.0.5 peer-group DEF
 neighbor 10.10.0.9 peer-group DEF
 neighbor 10.10.0.13 peer-group DEF
 neighbor 169.254.0.1 peer-group INSIDE

С sw-ddos закончили. Переходим к ядру.

Core(config)#
!Делаем VRF
ip vrf DDOS
 rd 10:10
 route-target both 10:10

!Создаем статические маршруты из VRF в сторону ASA как для доступа к внутренним ресурсам, так и для маршрутизации в интернет в обычной ситуации.
ip route vrf DDOS 0.0.0.0 0.0.0.0 172.31.0.1 250
ip route vrf DDOS 10.0.0.0 255.0.0.0 172.31.0.1
ip route vrf DDOS 172.16.0.0 255.240.0.0 172.31.0.1
ip route vrf DDOS 192.168.0.0 255.255.0.0 172.31.0.1
!Да, маршрут на 0.0.0.0/0 имеет метрику 250 – нужно, чтобы внезапно пришедший от sw-ddos BGP маршрут на тот же префикс мог перекрыть статику.

!Нужны route-map’ы для BGP. Мы можем принять от sw-ddos только дефолтный маршрут, или маршрут на лупбек. Для принятого маршрута ставим большой Local Preference, ведь мы будем создавать анонс на 0.0.0.0/0 локально, и надо, чтобы маршрут от Защитников, как только он прилетит, был сильнее:
ip prefix-list from-def seq 5 permit 0.0.0.0/0
ip prefix-list from-def seq 10 permit 192.168.0.15/32
route-map from-def permit 5
 match ip address prefix-list from-def
 set local-preference 200

!А еще мы выдадим тому свитчу полный комплект маршрутов на приватные сети. В принципе, только для management целей.
ip prefix-list private-nets seq 5 permit 10.0.0.0/8
ip prefix-list private-nets seq 10 permit 192.168.0.0/16
ip prefix-list private-nets seq 15 permit 172.16.0.0/12
route-map to_bgp_ddos permit 5
 match ip address prefix-list private-nets

!Теперь BGP. Он исключительно внутренний, потому AS приватная. Пиринг со свитчем мы поднимаем исключительно внутри VRF.
router bgp 65000
address-family ipv4 vrf DDOS
  redistribute static route-map to_bgp_ddos
  neighbor 169.254.0.2 remote-as 11111
  neighbor 169.254.0.2 activate
  neighbor 169.254.0.2 soft-reconfiguration inbound
  neighbor 169.254.0.2 route-map from-def in
  no synchronization
  network 0.0.0.0

!А вот это – адресация одного из VLANов. Все помнят, что площадок может быть несколько, и мы не хотим транжирить узкое адресное пространство?
  network 198.51.103.0 mask 255.255.255.240

!И надо бы анонсировать линк до ASA, чтобы гипотетическим iBGP пирам выдавать next hop'ом сразу адрес ASA.
network 172.31.0.0 mask 255.255.255.248

!Ах да, забыли про интерфейс до sw-ddos: 
interface GigabitEthernet2/0/6
 no switchport
 ip address 169.254.0.1 255.255.255.252

!Напоследок, создадим VLAN, в котором окажутся сервера:
interface Vlan500
ip vrf forwarding DDOS
 ip address 198.51.103.0 255.255.255.240

Всё сделано. Осталось лишь посмотреть, как все это выглядит. Вот когда все хорошо:

Core#show ip bgp vpnv4 vrf DDOS
BGP table version is 19376, local router ID is 192.168.0.16
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
Route Distinguisher: 10:10 (default for vrf DDOS)
*> 0.0.0.0          172.31.0.1            0    100      0 i
*> 10.0.0.0         172.31.0.1            0    100      0 ?
*> 198.51.103.0/28  0.0.0.0               0         11111 i
*> 172.16.0.0/12    172.31.0.1            0    100      0 ?
*> 192.168.0.0/16   172.31.0.1            0    100      0 ?
*> 192.168.0.15/32  169.254.0.2           0    200      0 11111 i
sw-ddos#show ip bgp 
BGP table version is 136, local router ID is 192.168.0.15
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale, m multipath, b backup-path, x best-external
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
*> 10.0.0.0         169.254.0.1              0             0 65000 ?
s  198.51.103.0/28  169.254.0.1              0             0 65000 i
*> 198.51.103.0/24  0.0.0.0         4294967295         11111 i
*> 172.16.0.0/12    169.254.0.1              0             0 65000 ?
*> 172.31.0.0/29    169.254.0.1              0             0 65000 i
*> 192.168.0.0/16   169.254.0.1              0             0 65000 ?
*> 192.168.0.15/32  0.0.0.0                  0         11111 i

Вроде все готово, пора приступать к тестированию. Защитники выдают нам маршрут на 0.0.0.0/0 и выпускают от себя наружу полученный от нас 198.51.103.0/24 (я, кажется, забыл упомянуть, что мы должны внести соответствующую запись в RIPE, иначе магистральщики не примут от них префикс). С 10.10.0.5 прилетел маршрут с MED 50, а от 10.10.0.1 MEDа вообще не было, потому «bgp bestpath med missing-as-worst» поставил там нечто большое и страшное.

sw-ddos#show ip bgp 
BGP table version is 9, local router ID is 192.168.0.15
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale, m multipath, b backup-path, x best-external
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
*  0.0.0.0          10.10.0.1       4294967295             0 2222 i
*>                  10.10.0.5               50             0 2222 i
*> 10.0.0.0         169.254.0.1              0             0 65000 ?
s> 198.51.103.0/28  169.254.0.1              0             0 65000 i
*> 198.51.103.0/24  0.0.0.0         4294967295         11111 i
*> 172.16.0.0/12    169.254.0.1              0             0 65000 ?
*> 192.168.0.0/16   169.254.0.1              0             0 65000 ?
*> 192.168.0.90/32  0.0.0.0                  0         11111 i

А вот как оно долетело до ядра:

core#show ip bgp vpnv4 vrf DDOS        
BGP table version is 19312, local router ID is 192.168.0.16
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
Route Distinguisher: 10:10 (default for vrf DDOS)
*> 0.0.0.0          169.254.0.2           0    200      0 11111 2222 i
*> 10.0.0.0         172.31.0.1            0    100      0 ?
*> 198.51.103.0/28  0.0.0.0               0         11111 i
*> 172.16.0.0/12    172.31.0.1            0    100      0 ?
*> 192.168.0.0/16   172.31.0.1            0    100      0 ?
*> 192.168.0.15/32  169.254.0.2           0    200      0 11111 i

Проверка через несколько произвольных looking glass показала, что общее время расхождения маршрута – от полутора до двух минут. Разумеется, в течение этого времени снаружи будут недоступны абсолютно все ресурсы, размещенные в сети 198.51.103.0/24. Причина проста: мы принимаем маршрут на 0.0.0.0/0 мгновенно, а интернет узнает о 198.51.103.0/24 не сразу. Внешний пользователь отправляет SYN, тот пролетает через ASA (она это отмечает в таблице соединений) и попадает на сервер. Тот отзывается SYN ACK, который успешно промахивается мимо ASA, улетая через туннель. И когда клиент возвращает ACK, ASA успешно дропает этот пакет. Но две минуты – это не два часа, такое время простоя сервисов в исключительных ситуациях (например, при DDoS атаке...) допустимо.

Подведем итоги и рассмотрим преимущества и недостатки выбранной архитектуры.
Преимущества:
• Безграничная масштабируемость. Парой команд можно разместить VLAN с защищаемыми ресурсами на любой площадке. Можно легко добавить новые устройства, терминирующие GRE туннели до провайдеров. Можно резервировать линки от них до нескольких маршрутизаторов ядра без малейшего усложнения конфигурации.
• Максимальная защита ресурсов сетевых устройств от атак.
• Простота и надежность архитектуры.
• Отсутствие необходимости будить сетевика в момент начала атаки (формально – сведение к минимуму риска человеческой ошибки).

Недостатки:
• Нет сокрытия внутренней адресации защищенного от DDOS атак VRFа. Критичность этого оцениваю как примерно нулевую. В обычном DMZ продолжает использоваться NAT. Между DMZ и DDOS сегментами доступ ограничивается ASA. Ну узнают, что у нескольких публикуемых наружу ресурсов нет отдельных внутренних адресов – и что?
• А что будет, если атаковать начнут ресурсы, не размещенные в VRF DDOS? Правильно, им поплохеет вместе с каналами. Но на этот случай разработан отдельный план действий, о котором я рассказывать не буду, потому что он подразумевает наличие острого ножа и как-то связан с японским словом «харакири».
• После переключения на пару минут ломаются вообще все сервисы, расположенные в защищенной сети.
• Администраторы серверов по три раза переспрашивают, какой внутренний адрес надо ставить, и только потом до них доходит.

Автор: JDima

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js