вторник, 24 октября 2023 г.

Отказоустойчивый proxy-cache DNS кластер на Nginx

 Доменные контролеры часто выполняют функцию и корпоративного DNS-сервера, что может привести к их повышенной нагрузке или даже перезагрузке ОС. Но эта роль важна, т.к. при авторизации в домене динамически заводятся  A и PTR записи авторизованных в домене компьютеров и серверов. Для разгрузки AD DC от частых DNS запросов можно использовать кеширующий DNS-сервер (перед ним), но для того, чтобы сам кеш-DNS-сервер не стал точкой отказа, то их надо использовать 2, и для отслеживания их статуса, перед ними поставить UDP прокси-сервер. Проще это сделать на основе связки Nginx c keepalived. Keepalived кроме VRRP функционала должен также отслеживать статуc Nginx за счет постоянного выполнения скрипта (на основе "pidof nginx") или команды (killall -0 nginx) и тот и другой скрипт должны выдавать 0 в RC при наличии процесса.

Также на этих  2-х хостах необходимо установить по экземпляру DNS-cache "unbound" (или другой аналогичный) , который в свою очередь (но намного реже), обращается с DNS запросами к 2-м AD DC серверам.

В первой ноде Nginx  (10.0.0.131) должны быть прописаны, как backend два кэш-сервера:

- 127.0.0.1:53  (экземпляр кеш-сервера на своей же машинке , что и UDP-proxy сервер)

- 10.0.0.132:53  (экземпляр кеш-сервера на другом участнике VRRP кластера)

на втором Nginx (10.0.0.132):

- 127.0.0.1:53  (экземпляр кеш-сервера на своей же машинке , что и UDP-proxy сервер)

- 10.0.0.131:53  (экземпляр кеш-сервера на  другом участнике VRRP кластера)

VIP:10.0.0.130 (важно чтобы frontend слушал только VIP:53, т.к. настоящие IP:53 займет кеширующий сервер на этой  машине)





Cкрипт (на основе "pidof"):
nano /bin/check_nginx.sh
#!/bin/sh
if [ -z "`pidof nginx`" ]; then
  exit 1
fi
chmod 755 /bin/check_nginx.sh

вместо скрипта можно использовать только команду "killall -0 nginx"
тогда скрип с ОС заводить не надо.
=======================
Конфигурация Keepalived:
# (одинаковая для обоих хостов)
нужно проверить/убедиться что включена опция в ядре:
echo "net.ipv4.ip_nonlocal_bind=1" >> /etc/sysctl.conf && sysctl -p
#
global_defs {
  # Keepalived process identifier
  router_id nginx
}

# Script to check whether Nginx is running or not
vrrp_script check_nginx {
  script "/bin/check_nginx.sh"
  interval 2
}

# Virtual interface - The priority specifies the order in which the assigned interface to take over in a failover
vrrp_instance VI_01 {
  state BACKUP    # if MASTER proirty 120
  interface eth0
  nopreempt 
  virtual_router_id 130
  priority 110

  # The virtual ip address shared between the two NGINX Web Server which will float
  virtual_ipaddress {
    10.0.0.130/24
  }
  track_script {
    check_nginx
  }
}

=============
конфигурация Nginx:
(установка модуля)
yum install nginx-mod-stream

#======

/etc/nginx/nginx.conf
...
events {
worker_connections 1024;
}

stream {
  upstream backends {
    zone   backend 64k;
    server 127.0.0.1:53 fail_timeout=1s;
    server 10.0.0.131:53 fail_timeout=1s;   #for another nginx ip will: 10.0.0.132
  }
  server {
    listen 10.0.0.130:53 udp;
    listen 10.0.0.130:53;  # tcp
    proxy_pass backends;
    proxy_timeout 1s;
    proxy_responses 1;

  }
}

=====
Конфигурация unbound:
(обоих)
...
server:
interface: 127.0.0.1
access-control: 127.0.0.0/8 allow
interface: 10.0.0.131 # for another node 10.0.0.132
access-control: 10.0.0.0/8 allow
        cache-max-ttl: 14400
        cache-min-ttl: 3600
        hide-identity: yes
        hide-version: yes
        minimal-responses: yes
        prefetch: yes
    prefetch-key: yes
    msg-cache-size: 50m
    msg-cache-slabs: 2
    rrset-cache-size: 100m
    rrset-cache-slabs: 2
    key-cache-size: 128m
    key-cache-slabs: 2
    qname-minimisation: yes
...
forward-zone:
  name: "."
  forward-addr: 10.0.0.2
  forward-addr: 10.0.0.3
  forward-first: yes






пятница, 20 октября 2023 г.

Двойной NAT Сisco IOS

Для NAT с подменой source и destination IP на Cisco IOS нужно использовать функционал "ip nat enable" на интерфейсах. Например, чтобы попасть (c IP 10.0.2.158) на 22 порт устройства в "inside" сети  за "inside" интерфейсом (с source IP/net этого "inside" интерфейса  роутера),  обращаясь на виртуальный порт/IP внешнего Outside интерфейса этого роутера, NAT необходимо настроить следующим образом:

interface FastEthernet8
 description
Outside
 ip address 10.129.162.2 255.255.255.240
 ip nat enable
  !
!
interface GigabitEthernet0
 description Inside
 ip address 10.72.1.10 255.255.255.0
 ip nat enable


ip nat source static tcp 10.72.1.1 22 10.129.162.2 443 extendable

ip access-list extended nat
 permit tcp host 10.0.2.158 host 10.129.162.2 eq 443

ip nat source list nat interface GigabitEthernet0 overload

Команда на хосте 10.0.2.158 (который "видит" 10.129.162.2): 
ssh 10.129.162.2 -p 443 
приведет к открытию ssh сессии с 10.0.2.158 на 22-й порт 10.72.1.1 с source  IP: 10.72.1.10 (то есть хосту 10.72.1.1 не нужен маршрут к 10.0.2.158, а достаточно только связности внутри connected сети 10.72.1.0/24.






 



воскресенье, 27 августа 2023 г.

Двойное натирование в Cisco ASA (twice NAT)

Необходимо принять от партнера трафик в р2р линке на виртуальный наш IP (не входит р2р net) с source IP, который тоже не входит р2р сеть, после чего заменить destination и source IP (для доставки уже в своей сети, согласно существующей маршрутизации).


Делаем через ASDM

1) Прописываем маршрутизацию в нужные IP/интерфейсы для всех IP не входящих в р2р сеть (партнера и свой).

2) Заводим объекты "IP" и "сервисы" (типа Net_xxx, TCP_XXX) и настраиваем NAT. Во избежании пересечения NAT с другими, предыдущими трансляциями), максимально конкретизируем в настройках source, dest, service (TCP_port).



3) Очищаем трансляции на этих интерфейсах (обязательно!) командой (можно из ASDM) 

clear xlate interface partner

clear xlate interface inside

вторник, 6 июня 2023 г.

Транзит трафика в Cisco ACI между 2-я L3Out (в одном VRF, но с разным типом маршрутизации.)

 Возникла необходимость пропустить трафик (организовать маршрутизацию) между 2-я L3Out (один с OSPF, другой Static), которые находятся  в одном VRF, но на разных LEAF. Формально  ничего не должно мешать, но при создании контракта в L3Out c OSPF не анонсировался маршрут другого (статического L3Out). Возможно надо было просто включить Route Control Enforcement: "Import":

но в этом L3out уже анонсировались сотни маршрутов и работали сотни сервисов разных арендаторов и десятки ExtEPG (сетей со своими контрактами). И если этот пункт не был отмечен изначально, то сейчас его включать было рискованно для непрерывности трафика.

Необходимая для транзита сеть в ExtEPG в L3Out Static (LEAF_1):




Вариантом (недокументированным?) оказалось создать в L3Out (с OSPF, LEAF_2)  новый ExtEPG-дубликат с сетью  другого ExtEPG из L3Out (Static) (которая должна была бы импортироваться в L3Out с OSPF), но включить только один пункт (!) Export Route Control Subnet:


После этого маршрут из static L3Out появляется на внешнем маршрутизаторе, который связан по  OSPF  (OSPF L3Out). При добавлении контакта трафик начинает ходить.






понедельник, 15 мая 2023 г.

Подсчет в Cisco ACI кол-ва пустых EPG

При автоматизации ACI, каждому EPG раздается пул сетей, из большого диапазона (например /16), и в итоге приходит момент когда диапазон /16 тоже кончается. Переписывать код API потребуется в  крайнем случае, если не удастся удалить пустые  EPG и освободить их сети, чтобы они вернулись в пул IPAM.

Чтобы понять сколько Endpoint в каждом EPG (в пустом 0), можно проверить в web интерфейсе APIC:


Но когда EPG большое количество, то проще запустить скрипт в CLI интерфейсе APIC:

Вывод количества Endpoint в каждом EPG в диапазоне, например: 10.156/16:

 moquery -c fvSubnet | grep subnet- | grep uni/ | grep  10.156. | awk -F "/" '{print "S " substr($4,5), system("moquery -c fvCEp | grep -v BA:31:22 | grep -c "substr($4,5))}' >  /tmp/endpoints


цифры (1,4,1,3) над "S" это кол-во endpoint в EPG (по названию, в след. строке), заодно вырезаем из подсчета паразитный мак (у меня такой хх:31:22), из-за  хоста в Promiscuous  mode, если такой есть в системе.

Избавиться в cli APIC от кода выполнения AWK (0 или 1, стоит в конце названия EPG) не удалось, поэтому добавляем нормализующий знак "S" (спереди) чтобы создать  дополнительную колонку (для exсel), после чего сдвигаем всю эту колонку вниз на одну строку позицию (строку), сортируем и удаляем все строки  с "S". Интересно, что код ошибки AWK "1" точно совпадает EPG в котором 0 endpoint, но лучше ориентироваться на первую колонку, хотя вторую колонку , с кодом ошибки AWK тоже можно использовать как показатель: код 1, означает 0 endpoint в EPG.


Чтобы  точно понять, что EPG "заброшены" и никому давно не нужны, то можно собрать и даты создания EPG.

 Вывод времени создания EPG:

 moquery -c fvSubnet | grep subnet- | grep uni/ | grep  10.156. | awk -F "/" '{print "SSSSS " substr($4,5), system("moquery -c fvSubnet | grep "substr($4,5)"/ -A3 | grep modTs")}' > /tmp/timecreation


Тут нормализующими символами будут "SSSSS", равные по кол-ву знаков  параметру modTs (время создания EPG). Аналогично сдвигаем дату создания на одну позицию вниз, сортируем по названию EPG и совмещаем в excel таблицы рядом, согласно столбцов с названиями EPG. проверям что совпадает от начала до конца. Затем выборочно проверяем, что всё совпадает в web интерфейсе APIC и самые старые, пустые EPG удаляем средствами автоматизации, чтобы вернуть IPAM освободившиеся сети. 

Файлы в каталоге /tmp/  автоматически удаляются каждую ночь, поэтому скрипт надо запускать с утра, т.к. его отработка может занять несколько часов, если EPG несколько тысяч, и потом обработать эти файлы в excel.



понедельник, 9 января 2023 г.

Создание произвольных метрик в Zabbix агенте и их мониторинг задержек TCP соединений

 Для измерения задержек подключения к серверам и создания графа сетевого взаимодействия имеются продукты типа Cisco AppDynamics. Но в моей ситуации имеется только предустановленный zabbix agent и curl. 

Создаем метрику для измерения задержек при создании TCP соединения с хоста на сервер (DB например). Для этого будем использовать функционал CURL и на его основе создадим пользовательские метрики в zabbix агенте (добавить в /etc/zabbix/zabbix_agentd.conf   , рестарт:  service zabbix-agent restart). 

1) Измерение времени DNS-резолвинга fqdn сервера:

UserParameter=DNS_resolve_Time,curl -w "%{time_namelookup}\n" -o /dev/null -s "http://SQLXXXXX.foo.com:1433"

вывод: 0,0X sec.

2) Измерение времени установления TCP соединения (получение SYN ACK) от сервера:

UserParameter=TCP_Syn_Received_Time,curl -w "%{time_connect}\n" -o /dev/null -s "http://SQLXXXXX.foo.com:1433"

вывод: 0,0X sec.

Сумма 2-х значений - есть время создание TCP подключения от хоста к серверу(DB) по порту 1433. В Curl можно использовать "http" для определения времени TCP соединения независимо от слушающего протокола (4-го уровня) на стороне сервера. В случае, возврата "0" от Curl, значит TCP порт не слушает или запрещен. 

Также можно отслеживать количество открытых TCP сокетов следующим параметром:

3) UserParameter=net.tcp_conn,netstat -nta | wc -l

 Настройка элемента данных в сервере Zabbix.

1) Добавляем хост любым способом (если ещё не мониторится) через интерфейс zabbix agent (TCP/10050), применяем любой подходящий шаблон.

2) После появления "последних данных" для данного хоста, необходимо отклонировать любой элемент данных, дать новое название и указать в качестве ключа параметры выделенные зеленым цветом в п.п. 1-3, выше. 


3) Для отображения общего времени соединения (dns + tcp connect) удобно создать "стекируемый" график для данного хоста и выводить именно его.

Примерный вывод обоих метрик: