В этой статье хочу поделиться опытом установки и настройки межсетевого экрана на базе Linux RHEL, в частности RedOS.
Что же из себя представляет NGFW (Next Generation Firewall)? За основу я взял модель FW Check Point. А значит, как минимум:
Firewall Blade - Собственно сам брандмауэр
IPS - Intruder Prevention System - система обнаружения и блокировки атак на основе поведенческого анализа по базе сигнатур
IPSec - построение VPN-туннелей (site-2-site, client-2-site)
Application Control / URL Filtering - контроль приложений и фильтрация по URL
Antivirus / AntiBot - проверка на вирусы/боты на лету, анализ пакетов
SandBlast - песочница с очисткой активного содержимого в файлах
На текущий момент из всего списка компонентов реализовано только FW, IPS, IPSec VPN. Напомню, что все компоненты OpenSource, а сама RedOS бесплатна для домашнего использования.
Версии ПО:
RedOS Murom 7.3.3 (server-minimal)
Suricata 7.0.1
WireGuard 1.0
OpenVPN 2.6.0
ShadowSocks 2.9.1
StrongSwan 5.9.9
В качестве FW будем использовать nftables (в RedOS он хоть и встроен в ядро, самой утилиты управления нет, предполагается, что админ сам выберет утилиту firewalld, nft, iptables)
При настройке всех VPN-сервисов важно знать, что сети, выдаваемые клиентам не должны пересекаться, повторяться и т.п.
Сразу оговорю, все настройки лучше делать под root. Сейчас в меня посыпятся хейты, однако сразу сообщу, NGFW - это не пользовательская задача. И да, SSH-доступ следует открывать только для внутренних администраторов, с внешней стороны его лучше не открывать. Также PermitRootLogin ставить no, использовать sudoers и т.п. и желательно использовать ssh-ключи с паролем. И да, параметр Listen в /etc/ssh/sshd_config лучше указывать конкретный IP из внутренней сети.
Итак, приступим. Этап 1. Настройка FW
Разумеется первым, а вернее нулевым действием после установки чистой ОС ее надо обновить.
dnf update -y reboot
Во-первых необходимо установить и преднастроить FW, для этого ставим и настраиваем nftables. Предварительно проверяем, что же установлено.
iptables -V iptables v1.8.9 (nf_tables)
В выводе nf_tables означает, что в ядре используется nftables. В моем случае я использовал mininal server инсталляцию, поэтому никаких "обвесов" у меня нет. Но для общего случая следует проверить и по необходимости деинсталировать лишнее
Удаляем обвесы nftables
systemctl status firewalld systemctl stop firewalld systemctl disable firewalld dnf remove firewalld
Проверим все ли необходимые модули ядра загружены. xt_conntrack / nf_conntrack (контроль состояния сессий) и 802.1q (для поддержки VLAN)
lsmod | grep xt_conntrack lsmod | grep 8021q
Если таковых нет, необходимо проверить, доступны ли эти модули
modprobe xt_conntrack modprobe 8021q
Если ошибок нет, то добавляем модули для загрузки в boot time. Создаем файл /etc/modules-load.d/mymod.conf
xt_conntrack 8021q
Теперь установим необходимую утилиту nft и настроим запуск службы
dnf install nftables systemctl enable nftables --now
Далее в файле /etc/sysconfig/nftables.conf указываем откуда подгружать конфиг FW
include "/etc/nftables/mynetworkfw.nft"
Далее есть 2 варианта управления файрволом, через конфиг и службу, либо прямыми командами nft и сохранением конфига nft list ruleset >/etc/nftables/mynetworkfw.nft.Принципиально разницы нет, однако при перезагрузке службы Handle правил будет обнуляться (то же самое при перезагрузке системы в целом). При редактировании правил через команды nft, Handle будет уникальным.
Теперь собственно необходим дефолтовый конфиг nftables. В частности, input/output и сама цепочка forward. Ниже приведу примерный файл /etc/nftables/mynetworkfw.nft
table inet fw { chain incoming { type filter hook input priority filter; policy drop; ct state established,related accept ip saddr { 192.168.10.50, 192.168.20.25 } tcp dport 22 counter accept comment "SSH_admin" iifname "lo" accept comment "Localhost" # IPSec VPN Clients udp port 1194 counter accept comment "OpenVPN_clients" udp port 51820 counter accept comment "WireGuard_clients" udp port { 4500,500 } counter accept comment "IPSec_IKEv2_clients" tcp port 26789 counter accept comment "ShadowSocks_clients" } chain outgoing { type filter hook output priority filter; policy drop; ct state established,related accept ip daddr 192.168.1.1 udp dport 53 oifname "ens224.40" counter accept comment "DNS_UDP_requests" ip daddr 192.168.1.1 tcp dport 53 oifname "ens224.40" counter accept comment "DNS_TCP_requests" tcp dport { 80, 443, 21 } counter accept comment "FW_to_Inet" oifname "lo" accept comment "Localhost" } chain forwarding { type filter hook forward priority filter; policy drop; ct state established,related accept counter queue to 0 } }
Поясню по конфигу, 192.168.10.50, 192.168.20.25 это IP-адреса админов NGFW. 192.168.1.1 это наш роутер, подключенный в инет и осуществляющий NAT и играющий роль DNS-сервера локальной сети. Разумеется это лишь пример. Обратите внимание, что фильтрация трафика осуществляется не только на вход к серверу, но и на выход. Когда закончим настройку NGFW основная цепочка будет именно forwarding, тут будут правила NGFW. Забегаю наперед, counter queue to 0 - это уже IPS-правило, его надо будет указать уже после запуска Suricata. Кроме того, в FW уже преднастроены клиенты VPN с портами по умолчанию. Если порты в настройках VPN-сервисов указываете другие, то и в FW их надо учесть. Интерфейсы ens192 (external) и ens224 (internal), на последний из них приходит trunc (802.1q). Все настройки интерфейсов располагаются /etc/sysconfig/network-scripts/, где ifcfg-<interface> - настройки интерфейса, route-<interface> настройки маршрутов если на интерфейсе их не 1. Примеры таких настроек в спойлере
Настройки интерфейсов
ifcfg-ens192
TYPE="Ethernet" PROXY_METHOD="none" BROWSER_ONLY="no" BOOTPROTO="manual" DEFROUTE="yes" IPV4_FAILURE_FATAL="no" IPV6INIT="yes" IPV6_AUTOCONF="yes" IPV6_DEFROUTE="yes" IPV6_FAILURE_FATAL="no" IPV6_ADDR_GEN_MODE="stable-privacy" NAME="ens192" DEVICE="ens192" ONBOOT="yes" UUID="3cec767a-e4ba-3130-839e-5588d3602a81" IPADDR="192.168.1.254" NETMASK="255.255.255.0" GATEWAY="192.168.1.1" DNS1="192.168.1.1" DNS2="8.8.8.8"
узнать UUID интерфейса можно через nmcli con show
отсюда DNS попадут в /etc/resolv.conf, а GATEWAY в таблицу маршрутизации, DEFROUTE=yes означает, что маршрут 0.0.0.0/0.0.0.0 будет через GATEWAY
ifcfg-ens224
BOOTPROTO="none" DEVICE="ens224" ONBOOT="yes" TYPE="Ethernet"
Обратите внимание, что здесь нет особо никаких настроек. Это публикация интерфейса для использования в 802.1q. UUID здесь также не указан, чтобы NetworkManager не управлял этой заглушкой.
ifcfg-ens224.20
DEVICE=ens224.20 BOOTPROTO=none ONBOOT=yes IPADDR=192.168.20.1 PREFIX=24 NETWORK=192.168.20.0 VLAN=yes
после расписывания всех файлов конфигураций, рестартанем NetworkManager
systemctl restart NetworkManager
Итак, предварительно настроили FW. правила FW применяются "на лету", а значит при ручном написании правил через команду nft, создавая chain в таблице не спешите ставить drop, первоначально лучше ставить accept, чтобы не потерять подключение к серверу.
Этап 2. Установка Suricata.
По дефолту, в репозитории Fedora Extra (epel) есть пакет Suricata, однако он скомпилирован с ограничениями, да и версия Python нас не устроит, так что придется собирать из исходников. Установим репозиторий epel, скачиваем исходник Suricata и устанавливаем нужные компоненты для компиляции.
wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm yum localinstall epel-release-latest-7.noarch.rpm cd /usr/src wget https://www.openinfosecfoundation.org/download/suricata-7.0.1.tar.gz tar xzvf suricata-7.0.1.tar.gz rm -f suricata-7.0.1.tar.gz cd suricata-7.0.1/ dnf groupinstall "Development Tools" dnf install -y pcre2-devel libyaml-devel jansson-devel libpcap-devel pcapy python3-pcapy libcap-ng-devel file-devel lz4-devel rustc cargo dnf install -y libunwind libunwind-devel GeoIP-devel zlib zlib-devel libnetfilter_queue-devel libnetfilter_log-devel ./configure --enable-nfqueue --enable-nflog --prefix=/usr/ --sysconfdir=/etc/ --localstatedir=/var/ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py python get-pip.py python -m pip install pyyaml make make install-full
Дальше нам необходимо поправить несколько моментов. Во-первых, надо настроить запуск службы suricata. Для этого создаем файл /usr/lib/systemd/system/suricata.service
[Unit] Description=Suricata IDS/IDP daemon After=network.target Requires=network.target Documentation=man:suricata(8) man:suricatasc(8) Documentation=https://redmine.openinfosecfoundation.org/projects/suricata/wiki [Service] Type=forking Environment=LD_PREDLOAD=/usr/lib/libtcmalloc_minimal.so.4 Environment=CFG=/etc/suricata/suricata.yaml PID=/var/run/suricata/suricata.pid CapabilityBoundingSet=CAP_NET_ADMIN PIDFile=/var/run/suricata/suricata.pid ExecStart=/usr/bin/suricata -D -q 0 -q 1 -c $CFG --pidfile $PID -D ExecReload=/bin/kill -HUP $MAINPID ExecStop=/bin/kill $MAINPID PrivateTmp=yes InaccessibleDirectories=/home /root ReadOnlyDirectories=/boot /usr /etc [Install] WantedBy=multi-user.target
Далее делаем chmod 755 /usr/lib/systemd/system/suricata.service и systemctl daemon-reload. Проверяем права доступа к созданным папкам, файлам, и т.д. /var/run/suricata, /etc/suricata/, /var/log/suricata. Если все права выставлены верно, значит проблем с запуском не возникнет. Запускам службу и ставим в автозапуск. systemctl enable suricata --now
Далее в cron добавляем обновление баз и перезагрузку этих правил. crontab -e
0 0 * * * /usr/lib/suricata-update >>/var/log/suricata/update.log 5 0 * * * /usr/lib/suricatasc -c reload-rules
Этап 3. Часть 1. Установка WireGuard
Установка WireGuard в RedOS задача не тривиальная.
Для начала необходимо установить необходимые репозитории. В частности, от Oracle Linux 7.
cd wget https://yum.oracle.com/repo/OracleLinux/OL7/latest/x86_64/getPackage/oraclelinux-release-el7-1.0-17.el7.x86_64.rpm wget https://yum.oracle.com/repo/OracleLinux/OL7/latest/x86_64/getPackage/oraclelinux-developer-release-el7-1.0-6.el7.x86_64.rpm yum localinstall oraclelinux-release-el7-1.0-17.el7.x86_64.rpm yum localinstall oraclelinux-developer-release-el7-1.0-6.el7.x86_64.rpm
Потом выполнить преконфиг и установку в соответствии с Installation manual WireGuard
yum-config-manager --disable ol7_developer yum-config-manager --enable ol7_developer_UEKR6 yum-config-manager --save --setopt=ol7_developer_UEKR6.includepkgs='wireguard-tools*' dnf install wireguard-tools
После чего, эти репозитории можно отключить/удалить и т.п. Больше они не потребуются, но могут мешать. Лучше отключать после чего сделать очистку dnf clean packages
yum-config-manager --disable ol7_developer yum-config-manager --disable ol7_developer_UEKR6 # и д.р. пакеты от Oracle Linux. либо вручную в файлах /etc/yum.repos.d/.repo # установить параметр enable=0 # oraclelinux-developer-ol7.repo # oracle-linux-ol7.repo # uek-ol7.repo # virt-ol7.repo
После чего также проверяем наличие модуля ядра, его автозагрузку и т.п.
lsmod | grep wireguard modprobe wireguard echo wireguard >>/etc/modules-load.d/mymod.conf
Создаем ключи. Публичный ключ будет нужен клиентам, для подключения к нашему серверу. Приватный ключ используем в конфиге туннеля.
cd /etc/wireguard wg genkey | tee priv.key | wg pubkey > pub.key chmod 600 *.key
Настраиваем подключение wireguard. Создаем файл /etc/wireguard/wgtun.conf
[Interface] PrivateKey = 8Kfqf4QdHL1pBKxT1NknbC7k9JCjyRj6hO1Mj+a4yU8= Address = 172.16.0.1/23 ListenPort = 51820 # Далее настройки каждого клиента # Клиент 1 [Peer] PublicKey = OIhY7IdxElaDH0amgCiZnLXx22sFn8QV8t40iihLaz8= AllowedIPs = 172.16.0.2/30 # Клиент 2 [Peer] PublicKey = QKqUuHDAtSw/xYs2AywdqiRHvcr1UzBwrKY7nphU8xg= AllowedIPs = 172.16.0.5/30
После чего проверяем его, если ошибок нет, то включаем службу
wg-quick up wgtun systemctl enable wg-quick@wgtun.service
Этап 3. Часть 2. Установка OpenVPN / ShadowSocks
Установка OpenVPN простая, у RedOS есть 2 версии OpenVPN и OpenVPN-Гост. Кому какой нравится. Мне ГОСТ не требуется, поэтому тут все просто. dnf install openvpn -y
Пример конфигурации OpenVPN. Создание CA опишу ниже. Этот CA мы будем использовать для OpenVPN / StrongSwan. Обратите внимание, что критично для конфигураций OpenVPN - это размещение конфигов клиента и сервера. В общих чертах, указание port обязательно для server и необязательно для client. Запускать службу OpenVPN будем так: systemctl start openvpn@config.service (для файла конфигурации /etc/openvpn/config.conf), systemctl start openvpn-client@config.service (для файла /etc/openvpn/client/config.conf) или systemctl start openvpn-server@config.service (для файла /etc/openvpn/server/config.conf). В нашем случае это файл /etc/openvpn/server/myvpnserver.conf
port 1194 proto udp dev tun0 ca /etc/openvpn/server/myvpnserver/ca.crt cert /etc/openvpn/server/myvpnserver/server.crt key /etc/openvpn/server/myvpnserver/server.key crl-verify /etc/openvpn/server/myvpnserver/crl.pem dh /etc/openvpn/server/myvpnserver/dh.pem tls-server tls-timeout 120 tls-auth /etc/openvpn/server/myvpnserver/ta-srv.key 0 server 172.16.2.0 255.255.254.0 route 172.16.2.0 255.255.254.0 ;routes ;see DEFAULT in CCD ;DHCP-Option ;see DEFAULT in CCD ifconfig-pool-persist /etc/openvpn/server/00-universal/cips client-config-dir /etc/openvpn/server/00-universal/ccd management localhost 7510 /etc/openvpn/server/myvpnserver/pwd keepalive 10 120 comp-lzo persist-key persist-tun status /var/log/openvpn/myvpnserver-status.log log /var/log/openvpn/myvpnserver-log.log
Теперь перед запуском сервиса необходимо создать все используемые файлы и настроить SELinux
dnf install libsemanage libsemanage-python semanage port -a -t openvpn_port_t -p tcp 7510 mkdir /etc/openvpn/server/myvpnserver mkdir /etc/openvpn/server/myvpnserver/ccd mkdir /var/log/openvpn echo "superhiddenpassword" >/etc/openvpn/server/myvpnserver/pwd chmod 700 /etc/openvpn/server/myvpnserver/pwd openvpn --genkey --secret /etc/openvpn/server/myvpnserver/ta-srv.key
Файл cips OpenVPN создаст сам, в нем будет хранить закрепленные за пользователями/серверами IP-адреса. Про сертификаты, ключи Diffie-Hellman, списки отзыва сертификатов ниже, в разделе про StrongSwan. А пока проверим запуск OpenVPN (будут ошибки из-за отсутствующих файлов)
systemctl start openvpn-server@myvpnserver.service # увидели ошибку, теперь добавим в загрузку, но без запуска systemctl enable openvpn-server@myvpnserver.service
Установка же ShadowSocks не тривиальна и снова потребует сборки и компиляции
dnf install git pcre-devel asciidoc xmlto mbedtls-devel libsodium-devel libcares-devel libev-devel cd /usr/src git clone https://github.com/shadowsocks/shadowsocks-libev.git cd shadowsocks-libev/ git submodule update --init --recursive ./autogen.sh ./configure make make install
Создаем пользователя, папку конфигов и сервис (для удобства openvpn-like сервис)
adduser --system --no-create-home -s /sbin/nologin shadowsocks mkdir -p /etc/shadowsocks
Содержание файла /usr/lib/systemd/system/shadowsocks@.service
[Unit] Description=Shadowsocks proxy server [Service] User=root Group=root Type=simple ExecStart=/usr/local/bin/ss-server -c /etc/shadowsocks/%i.json -a shadowsocks -v start ExecStop=/usr/local/bin/ss-server -c /etc/shadowsocks/%i.json -a shadowsocks -v stop [Install] WantedBy=multi-user.target
Примерное содержание конфига ss (/etc/shadowsocks/main.json)
{ "server":"178.128.122.54", "server_port": 26789, "password":"your_password", "timeout": 300, "method": "aes-256-gcm", "fast_open": true }
Права и запуск службы
chmod 755 /etc/systemd/system/shadowsocks@.service systemctl daemon-reload systemctl enable shadowsocks@main.service --now
Этап 3. Часть 3. Установка и настройка StrongSwan (IPSec IKEv2)
Устанавливаем и запускаем
dnf install strongswan systemctl enable strongswan --now
Создаем CA (без него не построить туннели на базе сертификатов). Лучше такой CA не держать на сервере в публичной сети, по крайней мере его приватный ключ. Для этой задачи штатно можно использовать strongswan pki, openssl, либо готовый скрипт easy-rsa. Мы возьмем последний, поскольку будем делать универсальный CA для служб OpenVPN и StrongSwan.
dnf install easy-rsa # забираем установленный набор в папку mkdir /usr/ca chmod 700 /usr/ca cd /usr/ca cp -Rv /usr/share/easy-rsa/3.0.8/ ./ # Инициируем CA ./easyrsa init-pki ./easyrsa build-ca ./easyrsa gen-dh # Создаем сертификат для OpenVPN сервера ./easyrsa gen-req ovpn nopass ./easyrsa sign-req server ovpn ./easyrsa gen-crl # Копируем нужные ключи для OpenVPN cp ./pki/ca.crt /etc/openvpn/server/myvpnserver/ cp ./pki/issued/ovpn.crt /etc/openvpn/server/myvpnserver/server.crt cp ./pki/private/ovpn.key /etc/openvpn/server/myvpnserver/server.key cp ./pki/dh.pem /etc/openvpn/server/myvpnserver/ cp ./pki/crl.pem /etc/openvpn/server/myvpnserver/ # Можно запускать наш OpenVPN systemctl start openvpn-server@myvpnserver.service
Инициировали CA, выпустили сертификат, запустили OpenVPN. Что дальше? Настраиваем strongswan.
# Создаем новый тип сертификата IPSec cp ./x509-types/serverClient ./x509-types/ipsec # Заменяем строку extendedKeyUsage = serverAuth,clientAuth # на extendedKeyUsage = serverAuth, clientAuth, 1.3.6.1.5.5.7.3.17 # и добавляем Subject Alternative Names. Важно указать реальные IP и привязанные при наличии DNS subjectAltName=DNS:vpn.example.com,DNS:localhost,IP:127.0.0.1,IP:185.185.101.23,DNS:185.185.101.23 # В файл./vars добавляем переменные set_var EASYRSA_CERT_EXPIRE 3650 set_var EASYRSA_EXTRA_EXTS "DNS:vpn.example.com,DNS:localhost,IP:127.0.0.1,IP:185.185.101.23,DNS:185.185.101.23" # Все готово, выпускаем сертификат ./easyrsa gen-req swan nopass ./easyrsa sign-req ipsec swan # Проверяем наши сертификаты openssl x509 -noout -text -in ./pki/issued/swan.crt # Должны быть указаны параметры: X509v3 Extended Key Usage: TLS Web Server Authentication, TLS Web Client Authentication, 1.3.6.1.5.5.7.3.17 X509v3 Subject Alternative Name: DNS:vpn.example.com, DNS:localhost, IP Address: 127.0.0.1, IP Address:185.185.101.23, DNS:185.185.101.23 # Теперь копируем все необходимое cp ./pki/ca.crt /etc/strongswan/ipsec.d/cacerts/ca.pem cp ./pki/issued/swan.crt /etc/strongswan/ipsec.d/certs/swan.pem cp ./pki/private/swan.key /etc/strongswan/ipsec.d/private/swan.pem # Подключаем сертификат, в файл /etc/strongswan/ipsec.secrets вписываем приватный ключ : RSA swan.pem
Теперь пишем конфиг /etc/strongswan/ipsec.conf
config setup charondebug="ike 2, knl 2, cfg 2, net 2, esp 2, dmn 2, mgr 2" conn %default keyexchange=ikev2 ike=aes128-sha256-ecp256,aes256-sha384-ecp384,aes128-sha256-modp2048,aes128-sha1-modp2048,aes256-sha384-modp4096,aes256-sha256-modp4096,aes256-sha1-modp4096,aes128-sha256-modp1536,aes128-sha1-modp1536,aes256-sha384-modp2048,aes256-sha256-modp2048,aes256-sha1-modp2048,aes128-sha256-modp1024,aes128-sha1-modp1024,aes256-sha384-modp1536,aes256-sha256-modp1536,aes256-sha1-modp1536,aes256-sha384-modp1024,aes256-sha256-modp1024,aes256-sha1-modp1024! esp=aes128gcm16-ecp256,aes256gcm16-ecp384,aes128-sha256-ecp256,aes256-sha384-ecp384,aes128-sha256-modp2048,aes128-sha1-modp2048,aes256-sha384-modp4096,aes256-sha256-modp4096,aes256-sha1-modp4096,aes128-sha256-modp1536,aes128-sha1-modp1536,aes256-sha384-modp2048,aes256-sha256-modp2048,aes256-sha1-modp2048,aes128-sha256-modp1024,aes128-sha1-modp1024,aes256-sha384-modp1536,aes256-sha256-modp1536,aes256-sha1-modp1536,aes256-sha384-modp1024,aes256-sha256-modp1024,aes256-sha1-modp1024,aes128gcm16,aes256gcm16,aes128-sha256,aes128-sha1,aes256-sha384,aes256-sha256,aes256-sha1! dpdaction=clear dpddelay=300s rekey=no left=%any leftsubnet=0.0.0.0/0 leftcert=swan.pem right=%any rightdns=8.8.8.8,8.8.4.4 rightsourceip=172.16.4.0/23 conn IPSec-IKEv2 keyexchange=ikev2 auto=add conn IPSec-IKEv2-EAP also="IPSec-IKEv2" rightauth=eap-mschapv2 rightauthby2=pubkey rightsendcert=never eap_identity=%any conn CiscoIPSec keyexchange=ikev1 forceencaps=yes authby=xauthrsasig xauth=server auto=add
Клиентам StrongSwan нужны будут свои сертификаты в P12. Для OpenVPN можно использовать pem, либо при использовании eToken,ruToken,JaCarta и пр. - pfx с паролем. Для этого можно использовать встроенные в easyrsa командлеты. export-p7, export-p12.
Этап 4. Включение маршрутизации
Для включения маршрутизации вносим изменения в sysctl. /etc/sysctl.d/10-forward.conf
net.ipv4.ip_forward=1 net.ipv6.conf.all.forwarding=1 # Включаем "на лету". После переагрузки ОС параметры подтянутся автоматически. sysctl -p /etc/sysctl.d/10-forward.conf
Послесловие
Ну и в конце, после настроек необходимых VPN-сервисов не забывайте открывать для них входящие и исходящие правила на FW. Также для маршрутизации и NAT необходимо прописывать соответствующие правила МЭ.
