Русский
Русский
English
Статистика
Реклама

Iptables

Свой сервер видеоконференций Jitsi. Часть 1

03.02.2021 00:17:16 | Автор: admin
Это первая статья, в которой я расскажу, как поднять свой собственный сервер видеоконференций Jitsi-meet. Я планирую выпустить три статьи на эту тему:
  1. Свой сервер видеоконференций Jitsi.
    Jitsi и все необходимые службы работают на одном сервере + сервис Jibri (для записи видеоконференций на отдельном сервере).
  2. Свой высоконагруженный сервис видеоконференций Jitsi.
    Jitsi и все необходимые зависимые службы работают на разных серверах для получения высокой производительности.
  3. Свой мессенджер Matrix-synapse в связке с Jitsi-meet.
    Настройка Matrix на своем сервере и объединение с Jitsi для видеозвонков.

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


В моем случае схема была немного другой, потому что у меня сервер Jitsi и Jibri находятся за NAT, в качестве которого стоит сервер с debian 9 и на котором есть внешний и внутренний IP. Сервисы Jitsi и Jibri также можно разместить на одном сервере, но тогда на него будет большая нагрузка и, следовательно, серверу надо дать больше ресурсов. Ниже я дам мануал, который составил, собирая свою службу (на три сервера), но каждый может преобразовать его под себя в зависимости от верований и убеждений, ну и возможностей конечно.
Итак, подготовительный этап прост и известен каждому, кто умеет в linux. А если не знаком, то в этих ваших интернетах полно инструкций по развёртыванию linux-системы. Мы же поднимем с вами три debian 9 сервера (можно использовать другой дистрибутив, просто адаптировав мануал).
Рекомендуемые системные требования:
Для сервера с Jitsi-meet:
4 ядра с 2.0ГГц и 4 RAM
Для сервера с Jibri:
4 ядра с 2.0ГГц и 4 RAM
Для сервера с Jitsi и Jibri:
8 ядер с 2.0ГГц и 8 RAM
Ну, и, естественно, интернет с большой пропускной способностью.
Производительность с разными вариациями характеристик сервера можно посмотреть тут.

Еще одно немаловажное требование большинство команд надо делать от привилегированного пользователя, поэтому на сервере (на каждом сервере) сразу получим root-права.
# sudo -i

или
# su - root

Сразу хочу отметить тот факт, что сервер под Jibri должен быть без GUI (графического интерфейса) иначе Jibri, который имеет свой xorg, будет конфликтовать и откажется работать (долгие танцы с бубном помогут уладить их конфликт, но зачем все усложнять!?).
NAT-сервер
Если мы будем использовать NAT-сервер, тогда нам нужно настроить на нем безопасность и перенаправление, а для этого мы обратимся к iptables (хотя тут опять-таки дело вкуса). Создаем скрипт, которым настроим iptables:
# touch iptables_rules.sh

Дальше открываем файл, вставляем и корректируем под свои значения:
iptables_rules.sh
#! /bin/bashIPT="iptables"## Внешний интерфейсWAN=ens224WAN_IP=ВАШ_внешний_IP## Внутренний интерфейсLAN1=ens192LAN1_IP=ВАШ_внутренний_IPLAN1_IP_RANGE=192.168.0.0/24LAN2=IP_Jitsi## Очищаем все цепочки перед применением новых правил$IPT -F$IPT -F -t nat$IPT -F -t mangle$IPT -X$IPT -t nat -X$IPT -t mangle -X## Блокируем весь трафик, который не соответствует ни одному из правил$IPT -P INPUT DROP$IPT -P OUTPUT DROP$IPT -P FORWARD DROP## Разрешаем весь трафик в локалхост и локальной сети$IPT -A INPUT -i lo -j ACCEPT$IPT -A INPUT -i $LAN1 -j ACCEPT$IPT -A OUTPUT -o lo -j ACCEPT$IPT -A OUTPUT -o $LAN1 -j ACCEPT## Этот блок разрешает icmp-запросы (пинговать сервер) (опционально)$IPT -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT$IPT -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT$IPT -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT$IPT -A INPUT -p icmp --icmp-type echo-request -j ACCEPT## Открываем доступ в интернет самому серверу$IPT -A OUTPUT -o $WAN -j ACCEPT#$IPT -A INPUT -i $WAN -j ACCEPT## Разрешаем все установленные соединения и дочерние от них$IPT -A INPUT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT$IPT -A OUTPUT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT$IPT -A FORWARD -p all -m state --state ESTABLISHED,RELATED -j ACCEPT## Защита от наиболее распространенных сетевых атак. (опционально)## Отбрасываем все пакеты без статуса (опционально)$IPT -A INPUT -m state --state INVALID -j DROP$IPT -A FORWARD -m state --state INVALID -j DROP## Блокируем нулевые пакеты (опционально)$IPT -A INPUT -p tcp --tcp-flags ALL NONE -j DROP## Закрываемся от syn-flood атак (опционально)$IPT -A INPUT -p tcp ! --syn -m state --state NEW -j DROP$IPT -A OUTPUT -p tcp ! --syn -m state --state NEW -j DROP## Запрет доступа с определенных IP (опционально)#$IPT -A INPUT -s ipaddres -j REJECT## Разрешаем доступ в интернет из локальной сети$IPT -A FORWARD -i $LAN1 -o $WAN -j ACCEPT## Запрещаем доступ из интернета в локальную сеть (опционально)#$IPT -A FORWARD -i $WAN -o $LAN1 -j REJECT## Чтобы в локальной сети был интернет включаем nat$IPT -t nat -A POSTROUTING -o $WAN -s $LAN1_IP_RANGE -j MASQUERADE##Должен быть включен ip forwarding## Разрешаем ssh (порт 22 - это порт по умолчанию для ssh соединения, если вы его меняли, то обязательно значение 22 надо заменить своим, иначе будет потерян доступ к серверу)$IPT -A INPUT -i $WAN -p tcp --dport 22 -j ACCEPT## Перенаправление трафика на сервер JITSI$IPT -A FORWARD -i $WAN -d $LAN2 -p tcp -m tcp --dport 80 -j ACCEPT$IPT -A FORWARD -i $WAN -d $LAN2 -p tcp -m tcp --dport 443 -j ACCEPT$IPT -A FORWARD -i $WAN -d $LAN2 -p udp -m udp --dport 10000 -j ACCEPT$IPT -t nat -A PREROUTING -i $WAN -p tcp --dport 80 -j DNAT --to $LAN2$IPT -t nat -A PREROUTING -i $WAN -p tcp --dport 443 -j DNAT --to $LAN2$IPT -t nat -A PREROUTING -i $WAN -p udp --dport 10000 -j DNAT --to $LAN2$IPT -t nat -A POSTROUTING -j MASQUERADE

Сохраняем и закрываем файл.

После этого надо сделать файл исполняемым и запустить:
# chmod +x iptables_rules.sh# ./iptables_rules.sh

Правила мы установили, однако после перезагрузки сервера они пропадут. Для того, чтобы применить их перманентно, выполним следующее:
# iptables-save > /etc/iptables-conf/iptables_rules.ipv4

Откроем файл и вставим в конец файла правило для восстановления настроек:
# vim /etc/network/interfaces

post-up /sbin/iptables-restore < /etc/iptables-conf/iptables_rules.ipv4

Ну, и, естественно, надо разрешить пересылку пакетов, открываем файл:
# vim /etc/sysctl.conf

Находим строку и раскомментируем (если стоит 0, то меняем на 1)
net.ipv4.ip_forward = 1

Применяем правила:
# sysctl -p


Настраиваем сервер Jitsi
Первый сервер готов, и мы переходим ко второму серверу Jitsi.
Тут опять надо разрешить пересылку пакетов открываем файл:
# vim /etc/sysctl.conf

Находим строку и раскомментируем (если стоит 0, то меняем на 1)
net.ipv4.ip_forward = 1

Применяем правила:
# sysctl -p

Установим необходимые утилиты:
# apt-get update# apt-get install ufw iftop htop wget net-tools vim y


Далее настроим ufw (нам нет нужды прописывать похожие правила как на предыдущем сервере, а достаточно просто открыть некоторые порты):
# ufw allow 22# ufw allow 80/tcp# ufw allow 443/tcp# ufw allow 10000/udp# ufw enable

Будет запрошено подтверждение, вводим y (порт 22 это порт по умолчанию для ssh соединения, если вы его меняли, то обязательно значение 22 надо заменить своим, иначе будет потерян доступ к серверу).

Далее необходимо настроить имя хоста:
# hostnamectl set-hostname jitsi.mydnsname.com

Стоит отметить, что для полноценного использования Jitsi-meet необходимо доменное имя и белый IP, к которому привязано имя.
Переходим к установке.
# echo 'deb https://download.jitsi.org stable/' >> /etc/apt/sources.list.d/jitsi-stable.list# wget -qO -  https://download.jitsi.org/jitsi-key.gpg.key | apt-key add -

# apt-get install -y apt-transport-https# apt-get update

Если у вас еще не установлен веб-сервер, то самое время это сделать. Выберите сами apache2 или nginx, и go:
# apt-get -y install nginx (apache2)# apt-get -y install jitsi-meet

В процессе установки будет запрошен IP сервера или его dns имя. Если сервер должен работать с мобильными приложениями, то должно быть dns имя и ssl сертификат. Далее утилита спросит про сертификат ( первый вариант применим для автоматического подписания сертификата, при условии что IP адрес белый и есть dns-имя, второй если уже есть сертификат, но тогда надо будет еще указать пути, где лежат сертификаты). Важное замечание: для подключения андроид устройств нужно добавить третий сертификат и прописать к нему путь в apache/nginx.
По завершению установки мы перейдем к настройке.
Как уже и говорил, надо добавить еще один ssl-сертификат для устройств android. Для этого мы в конфигурацию добавим путь к этому сертификату (скажу сразу, что у вас пути могут отличаться, если вы делали это другим способом). Открываем файл конфигурации (apache2 или nginx):
Apache2:
# vim /etc/apache2/saites-avalieble/example.org.conf

Добавляем строку (внимательно смотрим пути и подставляем свои значения):
SSLCertificateChainFile /etc/ssl/example.org/SectigoRSADomainValidationSecureServerCA.crt

Должно получиться так:
SSLProtocol TLSv1 TLSv1.1 TLSv1.2SSLEngine onSSLProxyEngine onSSLCertificateFile /etc/ssl/jitsi.dnsname.com/jitsi.dnsname.com.crtSSLCertificateChainFile /etc/ssl/jitsi.dnsname.com/SectigoRSADomainValidationSecureServerCA.crtSSLCertificateKeyFile /etc/ssl/jitsi.dnsname.com/jitsi.dnsname.com.keySSLCipherSuite "EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA256:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EDH+aRSA+AESGCM:EDH+aRSA+SHA256:EDH+aRSA:EECDH:!aNULL:!eNULL:!MEDIUM:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4:!SEED"SSLHonorCipherOrder onHeader set Strict-Transport-Security "max-age=31536000"

Сохраняем и закрываем файл.

Nginx:
# vim  /etc/nginx/sites-available/jitsi.dnsname.com.conf

# Mozilla Guideline v5.4, nginx 1.17.7, OpenSSL 1.1.1d, intermediate configuration    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # TLSv1.3;    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;    ssl_prefer_server_ciphers off;    ssl_session_timeout 1d;    ssl_session_cache shared:SSL:10m;  # about 40000 sessions    ssl_session_tickets off;    add_header Strict-Transport-Security "max-age=63072000" always;    ssl_certificate /etc/ssl/jitsi.dnsname.com/fullchain.pem;     ssl_certificate_key /etc/ssl/jitsi.dnsname.com/privkey.pem;     root /usr/share/jitsi-meet;


Сохраняем и закрываем файл.
Для nginx мы не указываем отдельный сертификат, а объединяем два сертификата в один:
# cat /etc/ssl/jitsi.dnsname.com/jitsi.dnsname.com.crt /etc/ssl/jitsi.dnsname.com/SectigoRSADomainValidationSecureServerCA.crt >> /etc/ssl/jitsi.dnsname.com/fullchain.pem


Проверить цепочку сертификатов можно тут.

Далее настраиваем систему. Добавляем туда следующее (отметим, что в локальный адрес прописываем адрес сервера Jitsi, а в публичный белый IP, у нас это IP адрес первого сервера):
# vim /etc/jitsi/videobridge/sip-communicator.properties

org.ice4j.ice.harvest.NAT_HARVESTER_LOCAL_ADDRESS=<Local.IP.Address>org.ice4j.ice.harvest.NAT_HARVESTER_PUBLIC_ADDRESS=<Public.IP.Address>

Комментируем следующую строку:
org.ice4j.ice.harvest.STUN_MAPPING_HARVESTER_ADDRESSES


Далее для поддержания конференции на большое количество людей (более 100) добавляем следующие строки в файл:
# vim /etc/systemd/system.conf

system.conf
DefaultLimitNOFILE=65000DefaultLimitNPROC=65000DefaultTasksMax=65000


Сохраняем и закрываем файл.

Далее:
# apt-get -y install jigasi# systemctl daemon-reload# systemctl restart jitsi# cat /proc/`cat /var/run/jitsi-videobridge/jitsi-videobridge.pid`/limits


Настраиваем сервер Jibri
Теперь нам осталось только поднять сервер с Jibri. Это опционально и нужно только для того, чтобы иметь возможность транслировать конференцию или вести запись конференции.
Jibri можно поставить рядом с Jitsi на одном сервере, но тогда на сервер будет идти бОльшая нагрузка. Мы сделаем это на отдельном сервере, но практически те же самые шаги надо предпринять, чтобы поднять Jibri рядом с Jitsi.
И так, приступим.
Тут опять надо разрешить пересылку пакетов, открываем файл:
# vim /etc/sysctl.conf

Находим строку и раскомментируем (если стоит 0, то меняем на 1)
net.ipv4.ip_forward = 1

Применяем правила:
# sysctl -p

На следующем шаге нам необходимо убедиться, что модуль обратной связи доступен и работает:
# echo "snd-aloop" >> /etc/modules# modprobe snd-aloop# lsmod | grep snd_aloop

Далее установим стабильную версию Google Chrome:
# curl -sS -o - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add# echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list# apt-get -y update# apt-get -y install google-chrome-stable

Создадим директорию и пропишем политики:
# mkdir -p /etc/opt/chrome/policies/managed# echo '{ "CommandLineFlagSecurityWarningsEnabled": false }' >> /etc/opt/chrome/policies/managed/managed_policies.json

Скачаем и установим chromedriver:
# CHROME_DRIVER_VERSION=`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE`# wget -N http://chromedriver.storage.googleapis.com/$CHROME_DRIVER_VERSION/chromedriver_linux64.zip -P ~/# unzip ~/chromedriver_linux64.zip -d ~/# rm ~/chromedriver_linux64.zip# mv -f ~/chromedriver /usr/local/bin/chromedriver# chown root:root /usr/local/bin/chromedriver# chmod 0755 /usr/local/bin/chromedriver

Установим зависимости и необходимые пакеты:
# apt-get install ffmpeg curl alsa-utils icewm xdotool xserver-xorg-input-void xserver-xorg-video-dummy

Теперь устанавливаем Jibri:
Если установка на сервер Jitsi
# apt-get install -y jibri


Установка на отдельный сервер
# wget -qO - https://download.jitsi.org/jitsi-key.gpg.key | sudo apt-key add -# sh -c "echo 'deb https://download.jitsi.org stable/' > /etc/apt/sources.list.d/jitsi-stable.list"# apt-get update# apt-get install -y jibri


Далее необходимо добавить Jibri в группы пользователей:
# usermod -aG adm,audio,video,plugdev jibri

Для работы Jibri необходима Java 8:
# wget -O - https://adoptopenjdk.jfrog.io/adoptopenjdk/api/gpg/key/public | sudo apt-key add -# add-apt-repository https://adoptopenjdk.jfrog.io/adoptopenjdk/deb/# apt-get update# apt-get install -y adoptopenjdk-8-hotspot

Нужно настроить Java 8 по умолчанию для Jibri. Для этого открываем файл и заменяем слово java на полный путь:
# vim /opt/jitsi/jibri/launch.sh

/usr/lib/jvm/adoptopenjdk-8-hotspot-amd64/bin/java

Для хранения видео нам надо отвести на сервере специальную директорию. Для этого мы создадим отдельную директорию (по желанию можно создать другую директорию, ее надо будет указать в конфигурации):
# mkdir /srv/recordings

Дадим Jibri права на нее и сделаем владельцем:
# chown jibri:jibri /srv/recordings

Далее мы настроим Jitsi-сервер для того, чтобы он знал о существовании Jibri и дадим все необходимые настройки и разрешения. Если сервис Jibri на отдельном сервере, тогда переходим на сервер Jitsi.
Начнем с конфигурации Prosody. Открываем файл и вставляем в конец файла с подстановкой своих значений:
# vim /etc/prosody/conf.avail/jitsi.dnsname.com.cfg.lua

jitsi.dnsname.com.cfg.lua
-- internal muc component, meant to enable pools of jibri and jigasi clientsComponent "internal.auth.jitsi.dnsname.com" "muc"    modules_enabled = {        "ping";    }    storage = "memory"    muc_room_cache_size = 1000    VirtualHost "recorder.jitsi.dnsname.com"    modules_enabled = {        "ping";    }    authentication = "internal_plain"


Теперь создадим учетные записи для пользователей jibri и recorder (пароли, которые мы тут установим, понадобятся нам далее):
# prosodyctl register jibri auth.jitsi.dnsname.com PAsswDJibRI# prosodyctl register recorder recorder.jitsi.dnsname.com PaSSwdReCORD

Следующим нашим действием станет прописывание конфигурации Jicofo. Откроем и добавим в файл следующие строки:
# vim /etc/jitsi/jicofo/sip-communicator.properties

jicofo/sim-communicator-properties
org.jitsi.jicofo.jibri.BREWERY=JibriBrewery@internal.auth.jitsi.dnsname.comorg.jitsi.jicofo.jibri.PENDING_TIMEOUT=90


Далее настроим Jitsi-meet. Добавим/раскомментируем строки в файле:
# vim /etc/jitsi/meet/jitsi.dnsname.com-config.js

config.js
fileRecordingsEnabled: true, liveStreamingEnabled: true, hiddenDomain: 'recorder.jitsi.dnsname.com',


Хочу обратить внимание, что следующий шаг необходимо выполнить только в том случае, когда сервис Jibri находится на отдельном сервере.
Ранее мы уже установили на сервере Jitsi ufw и открыли порты 22, 80, 443. Сейчас нам надо открыть еще порт 5222, для этого:
# ufw allow 5222/tcp

Теперь вернемся на сервер Jibri и добавим в файл jibri.conf следующую конфигурацию (не забываем подставлять свои значения, тут же нам надо указать и пароли для jibri и recorder):
# vim /etc/jitsi/jibri/jibri.conf

jibri.conf
jibri {  // A unique identifier for this Jibri  // TODO: eventually this will be required with no default  id = ""  // Whether or not Jibri should return to idle state after handling  // (successfully or unsuccessfully) a request.  A value of 'true'  // here means that a Jibri will NOT return back to the IDLE state  // and will need to be restarted in order to be used again.  single-use-mode = false  api {    http {      external-api-port = 2222      internal-api-port = 3333    }    xmpp {      // See example_xmpp_envs.conf for an example of what is expected here      environments = [      {                name = "prod environment"                xmpp-server-hosts = ["jitsi.dnsname.com"]                xmpp-domain = "jitsi.dnsname.com"                control-muc {                    domain = "internal.auth.jitsi.dnsname.com"                    room-name = "JibriBrewery"                    nickname = "jibri-nickname"                }                control-login {                    domain = "auth.jitsi.dnsname.com"                    username = "jibri"                    password = "PAsswDJibRI"                }                call-login {                    domain = "recorder.jitsi.dnsname.com"                    username = "recorder"                    password = "PaSSwdReCORD"                }                strip-from-room-domain = "conference."                usage-timeout = 0                trust-all-xmpp-certs = true            }]    }  }  recording {    recordings-directory = "/srv/recordings"    # TODO: make this an optional param and remove the default    finalize-script = "/path/to/finalize_recording.sh"  }  streaming {    // A list of regex patterns for allowed RTMP URLs.  The RTMP URL used    // when starting a stream must match at least one of the patterns in    // this list.    rtmp-allow-list = [      // By default, all services are allowed      ".*"    ]  }  chrome {    // The flags which will be passed to chromium when launching    flags = [      "--use-fake-ui-for-media-stream",      "--start-maximized",      "--kiosk",      "--enabled",      "--disable-infobars",      "--autoplay-policy=no-user-gesture-required"    ]  }  stats {    enable-stats-d = true  }  webhook {    // A list of subscribers interested in receiving webhook events    subscribers = []  }  jwt-info {    // The path to a .pem file which will be used to sign JWT tokens used in webhook    // requests.  If not set, no JWT will be added to webhook requests.    # signing-key-path = "/path/to/key.pem"    // The kid to use as part of the JWT    # kid = "key-id"    // The issuer of the JWT    # issuer = "issuer"    // The audience of the JWT    # audience = "audience"    // The TTL of each generated JWT.  Can't be less than 10 minutes.    # ttl = 1 hour  }  call-status-checks {    // If all clients have their audio and video muted and if Jibri does not    // detect any data stream (audio or video) comming in, it will stop    // recording after NO_MEDIA_TIMEOUT expires.    no-media-timeout = 30 seconds    // If all clients have their audio and video muted, Jibri consideres this    // as an empty call and stops the recording after ALL_MUTED_TIMEOUT expires.    all-muted-timeout = 10 minutes    // When detecting if a call is empty, Jibri takes into consideration for how    // long the call has been empty already. If it has been empty for more than    // DEFAULT_CALL_EMPTY_TIMEOUT, it will consider it empty and stop the recording.    default-call-empty-timeout = 30 seconds  }}


Теперь нам осталось только перезапустить систему. Для этого введем следующие две команды: первую на сервере Jitsi, а вторую на Jibri соответственно (если оба сервиса стоят на одном сервере, то обе команды ввести на одном сервере):
# systemctl restart jitsi-videobridge2 prosody jicofo# systemctl enable --now jibri


Вот и готово. Теперь можно перейти в браузере на jitsi.dnsname.com запустить конференцию и включить ее запись. Видеофайлы можно найти на сервере Jibri в директории /srv/recordings. Забрать их с сервера можно множеством способов, я оставлю это на ваш полет фантазии, подскажу лишь несколько:
1. Настроить проброс портов (если сервер Jibri вы поставили за NAT), затем подключиться к серверу, например через WinSCP, и стянуть файл себе. То же самое можно сделать, только без проброса портов, если Jibri не за NAT и имеет внешний IP.
2. С помощью утилиты scp.

Сообщество Jitsi. Тут же взял мануал для Jibri.

Благодарю за внимание!
Благодарю Алексея Байко, Дарью Гулькович и Владислава Гедвило за внесенные правки.
Подробнее..

Xtables-addons фильтруем пакеты по странам

17.07.2020 18:15:01 | Автор: admin

Задача блокировки трафика из определенных стран кажется простой, но первое впечатление обманчиво. Сегодня расскажем, как это можно реализовать.

Предыстория


Результаты поиска в Google по этой теме огорчают: большинство решений давно протухли и порой кажется, что эту тему отложили в долгий ящик и навсегда забыли про нее. Мы же прошерстили много старых записей и готовы поделиться современной версией инструкции.
Рекомендуем прочитать статью полностью, прежде чем выполнять указанные команды.

Подготовка операционной системы


Фильтрация будет настраиваться с помощью утилиты iptables, которой требуется расширение для работы с GeoIP-данными. Такое расширение можно найти в xtables-addons. xtables-addons устанавливает расширения для iptables в виде самостоятельных модулей ядра, благодаря чему не нужно перекомпилировать ядро ОС.

На момент написания статьи актуальная версия xtables-addons 3.9. Тем не менее, в стандартных репозиториях Ubuntu 20.04 LTS можно найти только 3.8, а в репозиториях Ubuntu 18.04 3.0. Установить расширение из пакетного менеджера можно следующей командой:

apt install xtables-addons-common libtext-csv-xs-perl

Отметим, что между версией 3.9 и текущим состоянием проекта есть небольшие, но важные различия, о которых мы поговорим позднее. Для сборки из исходных кодов устанавливаем все необходимые пакеты:

apt install git build-essential autoconf make libtool iptables-dev libxtables-dev pkg-config libnet-cidr-lite-perl libtext-csv-xs-perl

Клонируем репозиторий:

git clone https://git.code.sf.net/p/xtables-addons/xtables-addons xtables-addons-xtables-addons

cd xtables-addons-xtables-addons

xtables-addons содержит множество расширений, но нас интересует только xt_geoip. Если не хочется тащить в систему ненужные расширения, их можно исключить из сборки. Для этого нужно отредактировать файл mconfig. Для всех желаемых модулей поставить y, а все ненужные отметить n. Собираем:

./autogen.sh

./configure

make

И устанавливаем с правами суперпользователя:

make install

Во время установки модулей ядра может возникнуть ошибка примерно такого содержания:

INSTALL /root/xtables-addons-xtables-addons/extensions/xt_geoip.koAt main.c:160:- SSL error:02001002:system library:fopen:No such file or directory: ../crypto/bio/bss_file.c:72- SSL error:2006D080:BIO routines:BIO_new_file:no such file: ../crypto/bio/bss_file.c:79sign-file: certs/signing_key.pem: No such file or directory

Такая ситуация возникает из-за невозможности подписать модули ядра, т.к. нечем подписывать. Решить эту проблему можно парой команд:

cd /lib/modules/(uname -r)/build/certs

cat <<EOF > x509.genkey

[ req ]default_bits = 4096distinguished_name = req_distinguished_nameprompt = nostring_mask = utf8onlyx509_extensions = myexts[ req_distinguished_name ]CN = Modules[ myexts ]basicConstraints=critical,CA:FALSEkeyUsage=digitalSignaturesubjectKeyIdentifier=hashauthorityKeyIdentifier=keyidEOF

openssl req -new -nodes -utf8 -sha512 -days 36500 -batch -x509 -config x509.genkey -outform DER -out signing_key.x509 -keyout signing_key.pem

Скомпилированный модуль ядра установлен, но система его не определяет. Попросим систему создать карту зависимостей с учетом нового модуля, а затем загрузим его:

depmod -a

modprobe xt_geoip

Убедимся, что xt_geoip загружен в систему:

# lsmod | grep xt_geoipxt_geoip               16384  0x_tables               40960  2 xt_geoip,ip_tables

Дополнительно убедимся, что расширение загрузилось в iptables:

# cat /proc/net/ip_tables_matches geoipicmp

Нас все устраивает и остается только добавить название модуля в /etc/modules, чтобы модуль заработал после перезагрузки ОС. С этого момента iptables понимает команды geoip, но ему не хватает данных для работы. Приступаем к загрузке базы данных geoip.

Получение базы данных GeoIP


Создаем каталог, в котором будет хранится информация, понятная расширению iptables:

mkdir /usr/share/xt_geoip

В начале статьи мы упоминали, что между версией из исходного кода и версией из пакетного менеджера есть различия. Самое заметное различие заключается в смене поставщика базы данных и скрипте xt_geoip_dl, который скачивает актуальные данные.

Версия из пакетного менеджера


Скрипт лежит по пути /usr/lib/xtables-addons, однако при попытке запуска можно увидеть не самую информативную ошибку:

# ./xt_geoip_dl unzip:  cannot find or open GeoLite2-Country-CSV.zip, GeoLite2-Country-CSV.zip.zip or GeoLite2-Country-CSV.zip.ZIP.

Ранее в качестве базы данных использовался продукт GeoLite, ныне известный как GeoLite Legacy, распространяемый по лицензии Creative Commons ASA 4.0 компанией MaxMind. С этим продуктом произошло сразу два события, которые сломали совместимость с расширением для iptables.

Во-первых, в январе 2018 года объявили о прекращении поддержки продукта, и второго января 2019 года с официального сайта убрали все ссылки на скачивание старой версии базы. Новым пользователям рекомендуется использовать продукт GeoLite2 или его платную версию GeoIP2.

Во-вторых, c декабря 2019 года MaxMind заявила о значительном изменении в доступе к их базам. Чтобы соответствовать Калифорнийскому закону о защите прав потребителей, компания MaxMind приняла решение прикрыть распространение GeoLite2 регистрацией.

Так как мы хотим воспользоваться их продуктом, зарегистрируемся на этой странице.


После на почту придет сообщение с просьбой установить пароль. Теперь, когда мы завели аккаунт, нужно создать лицензионный ключ. В личном кабинете находим пункт My License Keys, а затем нажимаем на кнопку Generate new License Key.

При создании ключа нам зададут только один вопрос: будем ли мы использовать этот ключ в программе GeoIP Update? Отвечаем отрицательно и нажимаем на кнопку Confirm. Во всплывающем окне будет отображен ключ. Сохраните этот ключ в надежное место, так как после закрытия всплывающего окна вы больше не сможете посмотреть ключ полностью.


У нас есть возможность скачивать базы GeoLite2 в ручном режиме, но их формат не совместим с форматом, который ожидает скрипт xt_geoip_build. Здесь на помощь приходят скрипты GeoLite2xtables. Для работы скриптов устанавливаем perl-модуль NetAddr::IP:

wget https://cpan.metacpan.org/authors/id/M/MI/MIKER/NetAddr-IP-4.079.tar.gz

tar xvf NetAddr-IP-4.079.tar.gz

cd NetAddr-IP-4.079

perl Makefile.PL

make

make install

Далее клонируем репозиторий со скриптами и записываем в файл полученный ранее лицензионный ключ:

git clone https://github.com/mschmitt/GeoLite2xtables.git

cd GeoLite2xtables

echo YOUR_LICENSE_KEY=\123ertyui123\' > geolite2.license

Запускаем в работу скрипты:

# Скачиваем данные GeoLite2./00_download_geolite2# Скачиваем информацию о странах (для соответствия коду)./10_download_countryinfo# Конвертируем GeoLite2 базу в формат GeoLite Legacy cat /tmp/GeoLite2-Country-Blocks-IPv{4,6}.csv |./20_convert_geolite2 /tmp/CountryInfo.txt > /usr/share/xt_geoip/dbip-country-lite.csv
MaxMind накладывает ограничение в 2000 скачиваний в сутки и при большом количестве серверов предлагает кэшировать обновление на прокси-сервере.
Обратите внимание, что выходной файл обязательно должен называться dbip-country-lite.csv. К сожалению, 20_convert_geolite2 выдает не идеальный файл. Скрипт xt_geoip_build ожидает три колонки:

  • начало диапазона адресов;
  • конец диапазона адресов;
  • код страны в iso-3166-alpha2.

А выходной файл содержит шесть колонок:

  • начало диапазона адресов (строковое представление);
  • конец диапазона адресов (строковое представление);
  • начало диапазона адресов (числовое представление);
  • конец диапазона адресов (числовое представление);
  • код страны;
  • название страны.

Это несоответствие критично и может быть исправлено одним из двух способов:

  1. править 20_convert_geolite2;
  2. править xt_geoip_build.

В первом случае сокращаем printf до нужного формата, а во втором изменяем присваивание переменной $cc на $row->[4]. После этого можно выполнять сборку:

/usr/lib/xtables-addons/xt_geoip_build -S /usr/share/xt_geoip/ -D /usr/share/xt_geoip

. . . 2239 IPv4 ranges for ZA  348 IPv6 ranges for ZA   56 IPv4 ranges for ZM   12 IPv6 ranges for ZM   56 IPv4 ranges for ZW   15 IPv6 ranges for ZW

Отметим, что автор GeoLite2xtables не считает свои скрипты готовыми для продакшена и предлагает следить за разработкой оригинальных скриптов xt_geoip_*. Поэтому перейдем к сборке из исходных кодов, в которой эти скрипты уже обновлены.

Версия из исходных кодов


При установке из исходных кодов скрипты xt_geoip_* располагаются в каталоге /usr/local/libexec/xtables-addons. В этой версии скрипта используется база данных IP to Country Lite. Лицензия Creative Commons Attribution License, а из доступных данных те самые необходимые три столбца. Скачиваем и собираем базу:

cd /usr/share/xt_geoip/

/usr/local/libexec/xtables-addons/xt_geoip_dl

/usr/local/libexec/xtables-addons/xt_geoip_build

После этих действий iptables готов к работе.

Используем geoip в iptables


Модуль xt_geoip добавляет всего два ключа:

geoip match options:[!] --src-cc, --source-country country[,country...]Match packet coming from (one of) the specified country(ies)[!] --dst-cc, --destination-country country[,country...]Match packet going to (one of) the specified country(ies)NOTE: The country is inputed by its ISO3166 code.

Способы формирования правил для iptables, в целом, остаются неизменными. Для использования ключей из дополнительных модулей необходимо явно указывать название модуля с ключом -m. Например, правило для блокировки входящих TCP-соединений на 443 порту не из США на всех интерфейсах:

iptables -I INPUT ! -i lo -p tcp --dport 443 -m geoip ! --src-cc US -j DROP

Файлы, созданные xt_geoip_build, используются только при создании правил, но не учитываются при фильтрации. Таким образом, для корректного обновления базы geoip необходимо сначала обновить iv*-файлы, а затем пересоздать все правила, которые используют geoip в iptables.

Заключение


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

Подробнее..

Перевод Используем nftables в Red Hat Enterprise Linux 8

15.07.2020 18:16:18 | Автор: admin

Статья подготовлена в преддверии старта курса Администратор Linux




В Red Hat Enterprise Linux 8 приоритетным низкоуровневым решением является nftables. В этой статье мы поговорим о том, как начать использовать nftables. Наиболее актуальной она будет для системных администраторов и DevOps-специалистов. Там, где это имеет смысл, мы поговорим о различиях между nftables и его предшественником iptables.


Для начала необходимо отметить, что nftables это userland-утилита, nft и подсистема ядра. Внутри ядра она строится на базе подсистемы netfilter. В этой статье мы будем говорить о взаимодействии пользователя с утилитой nft.


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


Примечание: в этой статье некоторые выходные данные могут быть достаточно длинными, поэтому мы сократим или уберем бесполезные или несущественные части вывода.

Начнем


Итак, как будет выглядеть настройка nftables по-умолчанию? Давайте выясним, выведя весь набор правил.


# nft list ruleset

В результате мы получим ничего. Ладно, это не очень интересно. О чем это говорит?


По умолчанию nftables не создает таблицы и цепочки, в отличие от своего предшественника iptables. Пустой набор правил имеет нулевую стоимость ресурсов. Для сравнения, вспомните iptables, где каждая предварительно созданная таблица и цепочка должны были учитываться, а базовые счетчики пакетов увеличивались, даже если в них было пусто.


Создание таблиц


В nftables вам понадобится создавать таблицы вручную. Таблицы должны определять семейство: ip, ip6, inet, arp, bridge или netdev. Здесь inet означает, что таблица будет обрабатывать пакеты ipv4 и ipv6. Именно это семейство мы и будем использовать в статье.


Примечание: Для тех, кто переходит с iptables, термин таблица может звучать неоднозначно. В nftables таблица просто пространство имен, ни больше, ни меньше. По сути, она представляет из себя набор цепочек, правил, наборов и иных объектов.

Давайте создадим нашу первую таблицу и перечислим набор правил.


# nft add table inet my_table# nft list rulesettable inet my_table {}

Отлично, теперь у нас есть таблица, но сама по себе она мало что дает. Давайте перейдем к цепочкам.


Создание цепочек


Цепочки объекты, которые будут содержать правила брандмауэра.


По аналогии с таблицами, цепочки также нужно создавать вручную. При создании цепочки необходимо указать, к какой таблице она относится, а также тип, хук и приоритет. В этом руководстве мы не будем ничего усложнять и используем filter, input, и priority 0 для фильтрации пакетов, предназначенных для хоста.


# nft add chain inet my_table my_filter_chain { type filter hook input priority 0 \; }

Примечание: Обратный слэш () нужен, чтобы shell не интерпретировал скобку как конец команды.

Цепочки также могут быть созданы без указания хука. Созданные таким образом цепочки эквиваленты цепочкам, созданным пользователями в iptables. Правила могут использовать операторы jump или goto для выполнения правил в цепочке. Эта механика полезна для логического разделения правил или для того, чтобы делиться подмножеством правил, которые в противном случае продублировались бы.


# nft add chain inet my_table my_utility_chain

Создание правил


Теперь, когда вы создали таблицу и цепочку, вы можете, наконец, добавить правила для брандмауэра. Давайте добавим правило для разрешения SSH.


# nft add rule inet my_table my_filter_chain tcp dport ssh accept

Здесь следует отметить, что как только мы добавили его в таблицу семейства inet, это единственное правило будет обрабатывать как пакеты IPv4, так и пакеты IPv6.


Глагол add будет добавлять правило в конец цепочки. Также вы можете использовать глагол insert, чтобы добавить правило в начало цепочки.


# nft insert rule inet my_table my_filter_chain tcp dport http accept

Мы добавили два правила, а теперь давайте посмотрим, как будет выглядеть полный набор правил.


# nft list rulesettable inet my_table {    chain my_filter_chain {    type filter hook input priority 0; policy accept;    tcp dport http accept    tcp dport ssh accept    }}

Обратите внимание, что правило http должно отрабатывать раньше правила ssh, поскольку мы использовали выше глагол insert.


Также вы можете добавить правило в произвольное место в цепочке. Есть два способа сделать это.


  1. Используйте index, чтобы указать на индекс в списке правил. Использование add добавит новое правило после указанного индекса. Если же вы используете insert, то новое правило будет добавлено перед правилом с заданным индексом. Значения индексов начинаются с 0.

# nft insert rule inet my_table my_filter_chain index 1 tcp dport nfs accept# nft list rulesettable inet my_table {    chain my_filter_chain {    type filter hook input priority 0; policy accept;    tcp dport http accept    tcp dport nfs accept    tcp dport ssh accept    }}# nft add rule inet my_table my_filter_chain index 0 tcp dport 1234 accept# nft list rulesettable inet my_table {    chain my_filter_chain {    type filter hook input priority 0; policy accept;    tcp dport http accept    tcp dport 1234 accept    tcp dport nfs accept    tcp dport ssh accept    }}

Примечание: Использование index с insert по факту эквивалентно опции iptables -I с индексом. Первое, о чем нужно помнить, так это о том, что индексы в nftables начинаются с 0. Во-вторых, индекс должен указывать на существующее правило. То есть писать "nft insert rule index 0" в пустой цепочке недопустимо.

  1. Используйте handle, чтобы указать правило, до или после которого нужно вставлять другое правило. Для вставки после используйте глагол add. Чтобы вставить до правила, используйте insert. Вы можете получить handle правил, добавив флаг handle при выводе правил.

# nft --handle list rulesettable inet my_table { # handle 21    chain my_filter_chain { # handle 1    type filter hook input priority 0; policy accept;    tcp dport http accept # handle 3    tcp dport ssh accept # handle 2    }}# nft add rule inet my_table my_filter_chain handle 3 tcp dport 1234 accept# nft insert rule inet my_table my_filter_chain handle 2 tcp dport nfs accept# nft --handle list rulesettable inet my_table { # handle 21    chain my_filter_chain { # handle 1    type filter hook input priority 0; policy accept;    tcp dport http accept # handle 3    tcp dport 1234 accept # handle 8    tcp dport nfs accept # handle 7    tcp dport ssh accept # handle 2    }}

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


Также вы можете получить handle правила во время создания, используя сразу два флага echo и handle. Правило будет выведено в CLI вместе с его handle.


# nft --echo --handle add rule inet my_table my_filter_chain udp dport 3333 acceptadd rule inet my_table my_filter_chain udp dport 3333 accept # handle 4

Примечание: старые версии nftables использовали позицию ключевого слова. С тех пор механика ключевых слов устарела и появился handle.

Удаление правил


Удаление правил выполняется с помощью handle правила по аналогии с командами add и insert выше.


Сначала нужно найти handle правила, которое вы хотите удалить.


# nft --handle list rulesettable inet my_table { # handle 21    chain my_filter_chain { # handle 1    type filter hook input priority 0; policy accept;    tcp dport http accept # handle 3    tcp dport 1234 accept # handle 8    tcp dport nfs accept # handle 7    tcp dport ssh accept # handle 2    }}

Затем используйте этот handle для удаления правила.


# nft delete rule inet my_table my_filter_chain handle 8# nft --handle list rulesettable inet my_table { # handle 21    chain my_filter_chain { # handle 1    type filter hook input priority 0; policy accept;    tcp dport http accept # handle 3    tcp dport nfs accept # handle 7    tcp dport ssh accept # handle 2    }}

Листинг правил


В примерах выше мы выводили весь список правил. Существует много других способов вывести подмножество правил.


Вывести все правила в заданной таблице.


# nft list table inet my_tabletable inet my_table {    chain my_filter_chain {        type filter hook input priority 0; policy accept;        tcp dport http accept        tcp dport nfs accept        tcp dport ssh accept    }}

Вывести правила в заданной цепочке.


# nft list chain inet my_table my_other_chaintable inet my_table {    chain my_other_chain {        udp dport 12345 log prefix "UDP-12345"    }}

Наборы


В nftables есть нативная поддержка наборов. Они могут оказаться полезными, если вы хотите, чтобы правило работало с несколькими IP-адресами, портами, интерфейсами или по любым другим критериям.


Анонимные наборы


Любое правило может иметь inline-наборы. Эта механика полезна для наборов, которые вы не собираетесь изменять.


Например, следующая команда будет разрешать весь трафик с 10.10.10.123 и 10.10.10.231.


# nft add rule inet my_table my_filter_chain ip saddr { 10.10.10.123, 10.10.10.231 } accept# nft list rulesettable inet my_table {    chain my_filter_chain {        type filter hook input priority 0; policy accept;        tcp dport http accept        tcp dport nfs accept        tcp dport ssh accept        ip saddr { 10.10.10.123, 10.10.10.231 } accept    }

Недостатком этого метода является то, что если вам нужно изменить набор, то нужно будет заменять и правило. Чтобы получить мутабельные наборы, нужно использовать именованные наборы.


В качестве другого примера, вместо первых трех правил мы могли бы использовать анонимный набор.


# nft add rule inet my_table my_filter_chain tcp dport { http, nfs, ssh } accept

Примечание: пользователи iptables скорее всего привыкли к использованию ipset. Поскольку в nftables есть собственная нативная поддержка наборов, ipset использовать не нужно.

Именованные наборы


Nftables также поддерживает мутабельные именованные наборы. Для их создания необходимо указать тип элементов, которые будут в них содержаться. Например, типы могут быть такими: ipv4_addr, inet_service, ether_addr.


Давайте создадим пустой набор.


# nft add set inet my_table my_set { type ipv4_addr \; }# nft list setstable inet my_table {    set my_set {    type ipv4_addr    }}

Чтобы сослаться на набор в правиле используйте символ @ и имя набора после него. Следующее правило будет работать как черный список для IP-адресов в нашем наборе.


# nft insert rule inet my_table my_filter_chain ip saddr @my_set drop# nft list chain inet my_table my_filter_chaintable inet my_table {    chain my_filter_chain {    type filter hook input priority 0; policy accept;    ip saddr @my_set drop    tcp dport http accept    tcp dport nfs accept    tcp dport ssh accept    ip saddr { 10.10.10.123, 10.10.10.231 } accept    }}

Конечно, это не особо эффективно, так как в наборе пусто. Давайте добавим в него несколько элементов.


# nft add element inet my_table my_set { 10.10.10.22, 10.10.10.33 }# nft list set inet my_table my_settable inet my_table {    set my_set {    type ipv4_addr    elements = { 10.10.10.22, 10.10.10.33 }    }}

Однако попытка добавить диапазон значений приведет к ошибке.


# nft add element inet my_table my_set { 10.20.20.0-10.20.20.255 }Error: Set member cannot be range, missing interval flag on declarationadd element inet my_table my_set { 10.20.20.0-10.20.20.255 }

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


Интервалы в наборах


В наборах также могут использовать диапазоны. Для IP-адресов это может быть крайне полезно. Для использования диапазонов, набор должен быть создан с использованием флагов интервалов.


# nft add set inet my_table my_range_set { type ipv4_addr \; flags interval \; }# nft add element inet my_table my_range_set  { 10.20.20.0/24 }# nft list set inet my_table my_range_settable inet my_table {    set my_range_set {    type ipv4_addr    flags interval    elements = { 10.20.20.0/24 }    }}

Примечание: Нотация маски сети была неявно преобразована в диапазон IP-адресов. Аналогично, мы могли бы написать 10.20.20.0-10.20.20.255 и получить тот же эффект.

Конкатенации наборов


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


В этом примере мы сможем сопоставлять IPv4-адреса, IP-протоколы и номера портов одновременно.


# nft add set inet my_table my_concat_set  { type ipv4_addr . inet_proto . inet_service \; }# nft list set inet my_table my_concat_settable inet my_table {    set my_concat_set {    type ipv4_addr . inet_proto . inet_service    }}

Теперь мы можем добавить элементы к списку.


# nft add element inet my_table my_concat_set { 10.30.30.30 . tcp . telnet }

Как видите, символьные имена (tcp, telnet) также можно использовать при добавлении элементов набора.


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


# nft add rule inet my_table my_filter_chain ip saddr . meta l4proto . tcp dport @my_concat_set accept# nft list chain inet my_table my_filter_chaintable inet my_table {    chain my_filter_chain {    ...    ip saddr { 10.10.10.123, 10.10.10.231 } accept    meta nfproto ipv4 ip saddr . meta l4proto . tcp dport @my_concat_set accept    }}

Также стоит отметить, что конкатенация может использоваться с inline-наборами. Вот последний пример, отражающий это.


# nft add rule inet my_table my_filter_chain ip saddr . meta l4proto . udp dport { 10.30.30.30 . udp . bootps } accept

Надеюсь, теперь вы понимаете всю силу наборов nftables.


Примечание: конкатенации наборов nftables аналогичны агрегатным типам ipset, например, hash:ip,port.

Verdict Map


Verdict map это интересная функция в nftables, которая позволит вам выполнить действие, основываясь на информации в пакете. Проще говоря, они сопоставляют критерии с действиями.


Например, чтобы логически разделить набор правил, вам нужны отдельные цепочки для обработки TCP и UDP пакетов. Вы можете использовать verdict map, чтобы направлять пакеты в эти цепочки с помощью одного правила.


# nft add chain inet my_table my_tcp_chain# nft add chain inet my_table my_udp_chain# nft add rule inet my_table my_filter_chain meta l4proto vmap { tcp : jump my_tcp_chain, udp : jump my_udp_chain }# nft list chain inet my_table my_filter_chaintable inet my_table {    chain my_filter_chain {    ...    meta nfproto ipv4 ip saddr . meta l4proto . udp dport { 10.30.30.30 . udp . bootps } accept    meta l4proto vmap { tcp : jump my_tcp_chain, udp : jump my_udp_chain }    }}

Конечно, по аналогии с наборами вы можете создавать мутабельные verdict map.


# nft add map inet my_table my_vmap { type inet_proto : verdict \; }

Ваши глаза вас не обманывают. Синтаксис с наборами и вправду очень схож. По факту, под капотом наборы и verdict map строятся на одном и том же типе данных.


Теперь вы можете использовать мутабельную verdict map в правиле.


# nft add rule inet my_table my_filter_chain meta l4proto vmap @my_vmap

Таблицы как пространства имен


Еще одна интересная вещь о таблицах в nftables это то, что они также являются полноценными пространствами имен. То есть две таблицы могут создавать цепочки, наборы и другие объекты с одинаковыми именами.


# nft add table inet table_one# nft add chain inet table_one my_chain# nft add table inet table_two# nft add chain inet table_two my_chain# nft list ruleset...table inet table_one {    chain my_chain {    }}table inet table_two {    chain my_chain {    }}

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


Однако и тут есть один нюанс. Каждый хук таблицы или цепочки можно рассматривать как независимый и отдельный брандмауэр. То есть пакет должен пройти через все, чтобы в итоге быть принятым. Если table_one принимает пакет, его все еще может отклонить table_two. Именно здесь в игру вступает приоритезация хуков. Цепочка с более низким приоритетом гарантированно будет выполнена перед цепочкой с более высоким приоритетом. Если приоритеты равны, то поведение не определено.


Сохранение и восстановление набора правил


Правила nftables можно с легкостью сохранить и восстановить. Вывод list в nft можно использовать в инструменте, чтобы провести восстановление. Именно так работает служба nftables systemd.


Сохранить набор правил


# nft list ruleset > /root/nftables.conf

Восстановить набор правил


# nft -f /root/nftables.conf

Конечно же, вы можете включить службу systemd и восстановить правила при перезагрузке. Служба читает правила из /etc/sysconfig/nftables.conf.


# systemctl enable nftables# nft list ruleset > /etc/sysconfig/nftables.conf

Примечание: некоторые дистрибутивы, включая RHEL-8, отправляют предопределенную конфигурацию nftables в /etc/nftables. Эти сэмплы часто включают в себя конфигурацию таблиц и цепочек в стиле iptables. Они часто указаны в файле /etc/sysconfig/nftables.conf, но могут быть закомментированы.

Заключение


Надеюсь, эта статья стала хорошим введением и демонстрацией возможностей nftables. Однако мы только коснулись поверхности nftables. Есть множество особенностей, которые здесь не затрагивались. Вы можете найти более подробную информацию на странице документации nft и в вики. Помимо этого, вы можете прочитать несколько следующих статей в этом блоге, в которых мы будем говорить о более продвинутых аспектах nftables.




Узнать подробнее о курсе Администратор Linux



Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru