Пусть у нас в fastdpi.conf заданы следующие девайсы:
in_dev=41-00.0 out_dev=41-00.1
Предположим, что нам требуется настроить в BIRD протокол BGP для uplink, то есть на девайсе 41-00.1.
in_dev=41-00.0 в этом примере), для него не надо создавать veth-пару.
Чтобы перенаправить BGP-трафик c 41-00.1 на роут-демон (BIRD), который работает в router netns, нам нужно создать veth-пару теневых для 41-00.1 интерфейсов.
Создаем router netns (имя router здесь выбрано произвольно, вы можете использовать другое имя netns), в котором будет работать BIRD:
ip netns add router
Создаем veth пару:
ip link add bng-w type veth peer name rib-w netns router
rib-интерфейс должен иметь IP-адрес (и IPv6, если IPv6 поддерживается). Этот адрес будет адресом BGP-пира для BGP-соседа.
ip netns exec router ip address add 10.0.0.4/24 broadcast 10.0.0.255 dev rib-w ip netns exec router ip address add 2098::4/124 dev rib-w ip netns exec router ip link set dev rib-w arp on ip netns exec router ethtool -K rib-w tx off
Где:
rib-w IPv4- и IPv6-адрес. Этот адрес будет адресом BGP-пира для BGP-соседа.ip link set dev rib-w arp on включает ARP на интерфейсе.ethtool -K rib-w tx off отключает аппаратный расчёт контрольной суммы (tx checksum offload). На некоторых сборках ядра, как минимум в CentOS 8, контрольная сумма на интерфейсе может рассчитываться некорректно.
Все команды выполняются внутри netns router (через ip netns exec router).
bras_arp_ip и bras_ipv6_address. Более того, во избежание непонятных ситуаций адреса bras_arp_ip и bras_ipv6_address не должны входить ни в какую подсеть, отводимую на TAP-интерфейсы.
DPI-интерфейс не должен иметь ни IPv4, ни IPv6 адреса, так как в СКАТ он используется как TAP-интерфейс и наличие на нем адресов не требуется (более того, даже может мешать, если сам интерфейс начнет генерировать и отправлять пакеты):
ip link set dev bng-w arp off # Disable IPv6 on dpiXXX interfaces (чтобы не было даже link-local адреса) echo 1>/proc/sys/net/ipv6/conf/bng-w/disable_ipv6
Наконец, поднимаем все созданные интерфейсы:
ip link set bng-w up ip netns exec router ip link set lo up ip netns exec router ip link set rib-w up
Не забывайте, что роут-демон (в этом примере — BIRD) должен быть запущен в router netns:
ip netns exec router /usr/local/sbin/bird
/usr/local/bin/bng_router.sh), который запускается при загрузке системы до старта роут-демона и fastDPI. Сам роут-демон (BIRD) запускайте через systemd-юнит в netns router после того, как скрипт отработает.
Пример скрипта /usr/local/bin/bng_router.sh:
#!/bin/bash # BIRD network namespace create and configuring process /sbin/ip netns add router # prepare BIRD interfaces /sbin/ip link add bng-w type veth peer name rib-w /sbin/ip link set rib-w netns router # To border /sbin/ip netns exec router ip link add link rib-w name vlan1111 type vlan id 1111 /sbin/ip netns exec router ip address add 192.168.27.8/28 broadcast 192.168.27.15 dev vlan1111 /sbin/ip netns exec router ip link set dev rib-w arp on # set tx checksum offload off /sbin/ip netns exec router ethtool -K rib-w tx off /sbin/ip link set dev bng-w arp off echo 1 > /proc/sys/net/ipv6/conf/bng-w/disable_ipv6 # LINKS UP /sbin/ip netns exec router ip link set lo up /sbin/ip netns exec router ip link set rib-w up /sbin/ip netns exec router ip link set vlan1111 up /sbin/ip link set bng-w up
Пример юнита BIRD (/etc/systemd/system/bird.netns.service). Юнит сам запускает скрипт bng_router.sh перед стартом BIRD (ExecStartPre), поэтому отдельно добавлять скрипт в автозагрузку не нужно:
[Unit] Description=BIRD Internet Routing Daemon executed in netns "router" Wants=network.target After=network.target Before=fastdpi.service [Service] Type=simple ExecStartPre=/usr/bin/bash /usr/local/bin/bng_router.sh ExecStartPre=/sbin/ip netns exec router /usr/sbin/bird -p -c /etc/bird.netns.conf ExecStart=/sbin/ip netns exec router /usr/sbin/bird -c /etc/bird.netns.conf -s /var/run/bird.netns.ctl -f -u bird -g bird ExecStartPost=/bin/bash -c "while test ! -e /var/run/bird.netns.ctl; do sleep 0.5; done && chmod 666 /var/run/bird.netns.ctl" ExecReload=/sbin/ip netns exec router /usr/sbin/birdc -s /var/run/bird.netns.ctl configure ExecStopPost=/bin/bash -c "while test ! -e /var/run/bird.netns.ctl; do sleep 0.5; done && rm -f /var/run/bird.netns.ctl" Restart=on-failure [Install] WantedBy=multi-user.target
41-00.1 link down, то СКАТ переведет в link down veth-интерфейсы этого девайса; как только линк 41-00.1 поднимется, СКАТ переведет veth-интерфейсы в link up.
tap и peer указать два конца veth-пары.
Ниже приведён сквозной пример: СКАТ с роутером, LAG на стороне LAN и WAN и пятью VRF. Роут-демон BIRD работает в netns router. Три файла согласованы между собой: имена veth-пары (bng/rib, bng-static/rib-static), номера таблиц ядра и подсети совпадают.
1. Стартовый скрипт /usr/local/bin/bng_router.sh создаёт netns router, veth-пары и VLAN-интерфейс. Запускается из юнита bird.netns.service до старта BIRD и fastdpi.
#!/bin/bash # BIRD network namespace create and configuring process /sbin/ip netns add router # prepare router interfaces /sbin/ip link add bng-w type veth peer name rib-w /sbin/ip link set rib-w netns router /sbin/ip link add bng-static type veth peer name rib-static /sbin/ip link set rib-static netns router /sbin/ip netns exec router ip address add 169.254.228.228/32 dev rib-static /sbin/ip netns exec router ip link add link rib-w vlan1111 name vlan1111 type vlan id 1111 /sbin/ip netns exec router ip address add 192.168.27.101/24 dev vlan1111 /sbin/ip netns exec router ip link set dev rib-w arp on /sbin/ip netns exec router ip link set dev rib-static arp on /sbin/ip netns exec router ethtool -K rib-static tx off /sbin/ip netns exec router ethtool -K rib-w tx off /sbin/ip link set dev bng-w arp off /sbin/ip link set dev bng-static arp off /sbin/ip link set bng-w up /sbin/ip link set bng-static up /sbin/ip netns exec router ip link set lo up /sbin/ip netns exec router ip link set rib-w up /sbin/ip netns exec router ip link set rib-static up /sbin/ip netns exec router ip link set vlan1111 up /sbin/ip netns exec router ip link add lo0 type dummy /sbin/ip netns exec router ip address add <IP-адрес loopback>/32 dev lo0 /sbin/ip netns exec router ip link set lo0 up exit 0
2. Конфигурация СКАТ — в /etc/dpi/fastdpi.conf добавить параметры роутера (router, router_netns, router_default_vrf и др.), а также блоки lag, router_device и router_vrf.
# FastDPI configuration parameters
#
# Interface pairs for ethernet bridge
#
# For example this setup
# in_dev=01-00.0:01-00.2
# out_dev=01-00.1:01-00.3
# creates following bridges:
# 01-00.0 <--> 01-00.1
# 01-00.2 <--> 01-00.3
#
dpdk_device=10:pci:00:13.0,desc='To subscriber'
dpdk_device=11:pci:00:14.0,desc='To internet'
dpdk_device=20:pci:00:16.0,desc='To subscriber'
dpdk_device=21:pci:00:15.0,desc='To internet'
in_dev=10:20
out_dev=11:21
router_max_ip4_route_count=100
router_max_ip6_route_count=20
#Scale factor is about 1 for every 1 Gigabit of total bandwidth
scale_factor=1
num_threads=2
#FDPI/CLI Control
ctrl_port=29000
ctrl_dev=lo
federal_black_list=False
black_list_redirect=http://vasexperts.ru/test/blocked.php
nat_exclude_private=1
mem_preset=1
forward_packet_priority=6
enable_auth=1
enable_acct=1
netflow=4
netflow_timeout=60
auth_servers=127.0.0.1%lo:29002
bras_enable=1
bras_arp_ip=127.0.0.1
bras_arp_mac=be:be:be:be:be:be
bras_dhcp_mode=2
bras_dhcp_ratelimit=16
bras_dhcp_disconnect=0x000B
bras_dhcp_timeout=17
bras_terminate_l2=1
bras_arp_proxy=0x006
bras_term_by_as=0
bras_terminate_local=0
bras_vlan_terminate=0
bras_dhcp_shcv_interval=60
bras_subs_id=qinq+mac,vlan+mac,mac
router_default_vrf=vrf-grt
router=1
router_netns=router
router_kernel_table=101
router_subs_announce=6
# BEGIN LAG CONFIGURATION
lag {
name=WAN
short_timeout=on
lacp=2
device=11
device=21
}
# END LAG CONFIGURATION
# BEGIN LLDP CONFIGURATION
lldp {
enable=on
device=10;desc=Te1/1;enable=on
device=20;desc=Te2/2;enable=on
device=11;desc=Te1/1;enable=on
device=21;desc=Te2/2;enable=on
system_name=bras800demo
system_desc=172.16.2.1/32
}
# END LLDP CONFIGURATION
# BEGIN IN LAG CONFIGURATION
lag {
name=LAN
short_timeout=on
lacp=2
device=10
device=20
}
# END IN LAG CONFIGURATION
# BEGIN ROUTER DEVICES CONFIGURATION
router_device {
vrf=vrf-grt
device=11
tap=bng-w
peer=rib-w
subnet=224.0.0.5/32
subnet=224.0.0.6/32
subnet=172.16.25.169/31
subnet=192.168.27.101/24
}
# END ROUTER DEVICES CONFIGURATION
# BEGIN ROUTER STATIC-DEVICE CONFIGURATION
router_device {
vrf=vrf-static
device=11
tap=bng-static
peer=rib-static
subnet=169.254.228.228/32
}
# END ROUTER STATIC-DEVICE CONFIGURATION
# BEGIN VRFs CONFIGURATION
router_vrf {
id=vrf-grt
netns=router
kernel_table=200
neighbor_cache=shared
}
router_vrf {
id=vrf-local
netns=router
kernel_table=203
neighbor_cache=shared
}
router_vrf {
id=vrf-inet
netns=router
kernel_table=202
neighbor_cache=shared
}
router_vrf {
id=vrf-static
netns=router
kernel_table=204
neighbor_cache=shared
}
router_vrf {
id=vrf-iptv
netns=router
kernel_table=201
neighbor_cache=shared
}
# END VRFs CONFIGURATION
bras_vrf_isolation=1
netflow_bill_method=1
ipfix_dev=vlanens18
ipfix_nat_udp_collectors=172.16.2.1:12345
ipfix_mtu_limit=1460
ajb_udpi_path=/mnt/dump/dpi
syslog_level=4
3. Конфигурация BIRD — /etc/bird.netns.conf: таблицы для каждого VRF, протоколы kernel (номера таблиц совпадают с kernel_table из fastdpi.conf), статические маршруты, BGP-сессия с аплинком и pipe между таблицами.
log syslog name "bird.netns" { trace, info, remote, warning, error, auth, fatal, bug };
#log "/var/log/bird.log" { info, remote, warning, error, auth, fatal, bug };
router id 192.168.27.101;
ipv4 table master4
ipv4 table GRT
ipv4 table LOCAL
ipv4 table INET
ipv4 table STATIC
ipv4 table IPTV
ipv4 table LNS
protocol device {
}
protocol direct {
ipv4 {table GRT;}; # Connect to default IPv4 table
ipv6; # ... and to default IPv6 table
}
function is_public() {
if net !~ [ 10.0.0.0/8+, 172.16.0.0/12+, 192.168.0.0/16+, 100.64.0.0/10+ ] then
return true;
return false;
}
function is_private() {
if net ~ [ 10.0.0.0/8+, 172.16.0.0/12+, 192.168.0.0/16+, 100.64.0.0/10+ ] then
return true;
return false;
}
filter default_gw {
if net ~ [0.0.0.0/0] || net ~ [9.0.0.0/8+] then
accept;
reject;
}
filter local_pub_and_pr_subnet {
if (source = RTS_INHERIT || source = RTS_STATIC) && (is_public() || (is_private() && (net.len != 32))) && (net !~ [0.0.0.0/0]) then
accept;
reject;
}
filter local_pr_subnet {
if (source = RTS_INHERIT) && is_private() && (net.len != 32) && (net !~ [ 2.92.40.0/21+ ] ) then
accept;
reject;
}
filter mcpe_proto_import {
if net ~ [10.255.102.224/28] then
accept;
reject;
}
filter mcpe_proto_export {
if proto = "INETstatic" then
accept;
reject;
}
protocol kernel {
ipv4 {
table master4;
import all;
export all;
};
learn;
}
protocol kernel k_grt {
ipv4 {
table GRT;
import all;
export all;
};
learn;
kernel table 200;
}
protocol kernel k_local {
ipv4 {
table LOCAL;
import all;
export all;
};
learn;
kernel table 203;
}
protocol kernel k_inet {
ipv4 {
table INET;
import all;
export all;
};
learn;
kernel table 202;
}
protocol kernel k_static {
ipv4 {
table STATIC;
import all;
export all;
};
learn;
kernel table 204;
}
protocol kernel k_iptv {
ipv4 {
table IPTV;
import all;
export all;
};
learn;
kernel table 201;
}
protocol static masterstatic {
ipv4 {table master4;};
# route <c.i.d.r/xx> via <i.p.n.h>
route 0.0.0.0/0 via 172.16.25.168 ;
route 192.168.10.5/32 via 169.254.228.1;
}
protocol static GRTstatic {
ipv4 {table GRT;}; # Again, IPv4 channel with default options
route 0.0.0.0/0 via 172.16.25.168 ;
}
protocol static LOCALstatic {
ipv4 {table LOCAL;}; # Again, IPv4 channel with default options
route 172.16.12.0/24 via "rib-w";
route 172.16.13.0/24 via "rib-w";
}
protocol static IPTVstatic {
ipv4 {table IPTV;}; # Again, IPv4 channel with default options
route 172.16.11.0/24 via "rib-w";
}
protocol static INETstatic {
ipv4 {table INET;}; # Again, IPv4 channel with default options
route 172.16.10.0/24 via "rib-w";
}
protocol bgp uplink1 {
debug { states };
description "to uplink1";
local 192.168.27.101 as 65000;
neighbor 172.16.25.168 as 65000 internal;
multihop;
ipv4 {
next hop self;
table GRT;
import all;
export filter local_pub_and_pr_subnet;
};
}
protocol pipe grt_iptv {
table GRT;
peer table IPTV;
import filter local_pub_and_pr_subnet;
export filter default_gw;
}
protocol pipe grt_inet {
table GRT;
peer table INET;
import filter local_pub_and_pr_subnet;
export filter default_gw;
}
protocol pipe grt_static {
table GRT;
peer table STATIC;
import filter local_pub_and_pr_subnet;
export filter default_gw;
}
protocol pipe grt_local {
table GRT;
peer table LOCAL;
import filter local_pub_and_pr_subnet;
export filter default_gw;
}
Роутер можно настроить как без VRF, так и с VRF. Если секции router_vrf не заданы, СКАТ работает с одной VRF по умолчанию: её netns и таблицу маршрутизации задают параметры router_netns и router_kernel_table.
Файл: /etc/dpi/fastdpi.conf. Минимальная конфигурация роутера для примера с veth-интерфейсами выше — в fastdpi.conf добавить:
in_dev=41-00.0
out_dev=41-00.1
router=1
router_netns=router
router_kernel_table=1
bras_arp_mac=00:E0:ED:43:84:42
bras_arp_ip=188.227.73.40
router_device {
device=41-00.1
tap=bng-w
peer=rib-w
subnet=10.0.0.0/24
}
Роут-демон должен строить таблицу маршрутизации ядра с тем же номером: в BIRD — kernel table 1 в протоколе kernel.
Файл: /etc/dpi/fastdpi.conf. Пример полной конфигурации с включённым роутером и двумя VRF (добавляется целиком или используется как основа для своей конфигурации):
in_dev=0b-00.0
out_dev=13-00.0
scale_factor=1
ctrl_port=29000
ctrl_dev=lo
federal_black_list=0
black_list_sm=1
black_list_redirect=http://vasexperts.ru/test/blocked.php
num_threads=1
router=1
router_vrf {
id=ROUTER
netns=router
kernel_table=100
neighbor_cache=shared
}
router_vrf {
id=ROUTER2
netns=router
kernel_table=101
neighbor_cache=shared
}
router_device {
device=13-00.0
vrf=ROUTER
tap=dpi_ospf
peer=rib_ospf
subnet=224.0.0.5/30
subnet=192.168.123.69/32
}
router_device {
device=13-00.0
vrf=ROUTER2
tap=dpi_bgp
peer=rib_bgp
subnet=192.168.123.70/32
}
router_subs_announce=6
enable_auth=1
auth_servers=127.0.0.1%lo:29002
bras_enable=1
bras_arp_ip=10.10.102.189
bras_arp_mac=00:0c:29:f5:85:47
bras_dhcp_mode=1
bras_dhcp_server=10.10.99.3%ens256;reply_port=67
bras_pppoe_enable=1
bras_pppoe_session=100
bras_ppp_auth_list=2,3,1
enable_acct=1
netflow=4
netflow_timeout=300
bras_pppoe_service_name=demoDPI
Простой пример BGP:
filter public_subnets {
if (net ~ [172.16.0.0/12+] || net ~ [192.168.0.0/16+] || net ~ [10.0.0.0/8+] || net ~ [127.0.0.0/8+] || net ~ [169.254.0.0/16+]) then reject;
accept;
}
protocol bgp bgp_ipv4 {
description "To border";
local 192.168.27.8 as 65000;
neighbor 192.168.27.1 as 65000;
direct;
ipv4 {
import all;
export filter public_subnets;
}
}
Простой статический протокол, когда нужно объявить широкую абонентскую подсеть целиком:
protocol static {
ipv4;
route 100.69.0.0/16 blackhole;
}
# Указать дополнительные функции для проверки:
# Любой публичный адрес
function is_public() {
if net !~ [ 10.0.0.0/8+, 172.16.0.0/12+, 192.168.0.0/16+, 100.64.0.0/10+ ] then
return true;
return false;
}
# Любой приватный адрес
function is_private() {
if net ~ [ 10.0.0.0/8+, 172.16.0.0/12+, 192.168.0.0/16+, 100.64.0.0/10+ ] then
return true;
return false;
}
# Шлюз по умолчанию
filter default_gw {
if net ~ [0.0.0.0/0] then
accept;
reject;
}
# Описать фильтры:
# Маршруты, которые не получены из других протоколов маршрутизации (и префикс не /32)
filter exclude_external_routes {
if (source = RTS_INHERIT) && (net.len != 32) then
accept;
reject;
}
# Исключить маршруты из других протоколов маршрутизации, публичные подсети, приватные - не /32
filter exclude_ext_1_ip {
if (source = RTS_INHERIT) && (is_public() || (is_private() && (net.len != 32))) then
accept;
reject;
}
log "/var/log/bird.log" all;
router id 192.168.123.65;
debug protocols all;
# Описать таблицы
ipv4 table grt;
ipv4 table bird00;
ipv4 table bird01;
protocol device {
}
protocol direct {
disabled; # Отключено по умолчанию
ipv4; # Подключение к таблице IPv4 по умолчанию
ipv6; # ... и к таблице IPv6 по умолчанию
}
# Описать "протоколы" kernel
protocol kernel kernel_grt {
ipv4 { # Подключить протокол к таблице IPv4 по каналу
table grt;
import all; # Импорт в таблицу, по умолчанию - импортировать все
export all; # Экспорт в протокол. Значение по умолчанию - экспорт отсутствует
};
scan time 5;
learn; # Изучить пришедшие маршруты из kernel-таблицы
kernel table 99; # Kernel-таблица для синхронизации с (по умолчанию: основная)
}
protocol kernel kernel_bird00 {
ipv4 { # Подключить протокол к таблице IPv4 по каналу
table bird00;
import all; # Импорт в таблицу, по умолчанию - импортировать все
export all; # Экспорт в протокол. Значение по умолчанию - экспорт отсутствует
};
scan time 5;
learn; # Изучить пришедшие маршруты из kernel-таблицы
kernel table 100; # Kernel-таблица для синхронизации с (по умолчанию: основная)
}
protocol kernel kernel_bird01 {
ipv4 { # Подключить протокол к таблице IPv4 по каналу
table bird01;
import all; # Импорт в таблицу, по умолчанию - импортировать все
export all; # Экспорт в протокол. Значение по умолчанию - экспорт отсутствует
};
scan time 20;
learn; # Изучить пришедшие маршруты из kernel-таблицы
kernel table 101; # Kernel-таблица для синхронизации с (по умолчанию: основная)
}
# Другой экземпляр для IPv6, пропускающий параметры по умолчанию
protocol kernel {
ipv6 { export all; };
}
protocol static {
ipv4; # Снова канал IPv4 с параметрами по умолчанию
}
# Протоколы OSPF (каждый инстанс со своей таблицей)
protocol ospf v2 ospf_grt {
tick 1;
rfc1583compat no;
stub router no;
ecmp yes limit 16;
ipv4 {
table grt;
import all;
export all;
};
area 0.0.0.0 {
networks {
192.168.123.64/30;
};
interface "rib.102" {
cost 1;
rx buffer large;
type broadcast;
authentication none;
};
};
};
protocol ospf v2 ospf_bird01 {
tick 1;
rfc1583compat no;
ecmp yes limit 16;
ipv4 {
table bird01;
import all;
export all;
#export filter exclude_ext_1_ip;
};
area 0.0.0.0 {
networks {
192.168.123.68/30;
};
interface "rib.202" {
cost 1;
rx buffer large;
type broadcast;
authentication none;
};
};
}
# Описать "протоколы" маршрутизации, которые предназначены для "переливания" маршрутов между таблицами (с использованием фильтров)
protocol pipe grt_bird00 {
table grt;
peer table bird00;
import all;
export filter default_gw;
}
protocol pipe grt_bird01 {
table grt;
peer table bird01;
import all; # filter exclude_ext_1_ip;
export all; #filter default_gw;
}