Захист високопродуктивних шлюзів віртуальних приватних мереж (VPN) від компрометації хоста, несанкціонованого горизонтального переміщення та атак з підвищенням привілеїв вимагає рубежів безпеки, які діють глибше за стандартну дискреційну модель доступу (DAC). Класичні механізми прав доступу в Linux — на базі ідентифікаторів користувачів (UID), груп (GID) та привілеїв POSIX capabilities — виявляються беззахисними, якщо зловмисник отримує повноваження root усередині сусіднього контейнера або служби на тому ж сервері.

Історично для посилення безпеки застосовувалися системи мандатного контролю доступу (MAC), такі як SELinux або AppArmor. Попри високу надійність, цим класичним середовищам притаманні помітні експлуатаційні бар'єри: статичні конфігурації, громіздкі мови опису політик та потреба у повторній компіляції профілів чи перезапуску служб за будь-яких змін.

Починаючи з версії ядра Linux 5.7, модуль BPF LSM (інтеграція eBPF у структуру Linux Security Module) запропонував принципово іншу парадигму. Поєднуючи вбудовані точки перехоплення безпеки ядра з надійністю та швидкодією програм eBPF, інженери можуть у режимі реального часу впроваджувати динамічний мандатний контроль доступу для процесів VPN безпосередньо в ядрі — без редагування коду програм та без зупинки мережевих тунелів.

Вектори загроз: чому стандартна ізоляція має вразливості

Концентратори VPN та прикордонні вузли Zero-Trust обробляють критичні активи мережевої інфраструктури: нешифрований трафік користувачів та довготривалі криптографічні ключі (наприклад, статичні ключі Curve25519 у WireGuard).

У сучасному мультиорендному середовищі на одному вузлі разом із VPN часто функціонують допоміжні сервіси: агенти збору телеметрії, системи оркестрації та клієнти оновлення динамічного DNS. Звичайна модель безпеки операційної системи залишає відкритими кілька небезпечних шляхів проникнення:

[Вектори загроз для процесів VPN від скомпрометованих служб]
Скомпрометований процес (із привілеями root UID 0)
        │
        ├─► Вектор 1: ptrace() / process_vm_readv() ──► Викрадення ключів із RAM
        │
        ├─► Вектор 2: Доступ до /proc/$PID/mem ────────► Зчитування ключів сесії
        │
        ├─► Вектор 3: Перехоплення порту SO_REUSEPORT ─► Підслуховування UDP-рукостискань
        │
        └─► Вектор 4: sendmsg() із SCM_RIGHTS ────────► Витік дескрипторів із namespace
  1. Аналіз оперативної пам'яті через Ptrace: Отримавши права CAP_SYS_PTRACE або повноваження root у суміжному процесі, зловмисник може під'єднатися до процесу VPN за допомогою ptrace(2) або зчитати /proc/$PID/mem, вилучивши криптографічні ключі прямо з пам'яті.
  2. Перехоплення сокета та підміна порту: Створюючи сокет із прапорцями SO_REUSEADDR чи SO_REUSEPORT, шкідливий локальний процес може спробувати зайняти робочий порт UDP шлюзу VPN та перехоплювати пакети початкового криптографічного рукостискання.
  3. Несанкціоноване передавання дескрипторів: Дескриптори тунелів (інтерфейси TUN/TAP або мережеві сокети) можуть бути передані через сокети домену UNIX (SCM_RIGHTS) у сторонній процес, порушуючи ізоляцію мережевих просторів імен (network namespaces).

Архітектурні принципи підсистеми BPF LSM

Структура Linux Security Module визначає низку перевірочних точок — хуків (hooks), розміщених у критичних підсистемах ядра: керування процесами, обробка файлів, робота з дескрипторами та мережеві комунікації.

До появи BPF LSM ці точки були доступні лише компільованим модулям ядра. Із введенням типу програм BPF_PROG_TYPE_LSM операційна система дозволяє завантажувати безпечні програми eBPF безпосередньо у ці перевіркові рубежі.

[Конвеєр перевірки безпеки BPF LSM]
Дія процесу: наприклад sys_ptrace(PTRACE_ATTACH, vpn_pid)
                                │
                                ▼
                      Підсистема ядра Linux
                                │
                                ▼
                 Точка перехоплення: security_ptrace_access_check()
                                │
                 ┌──────────────┴──────────────┐
                 ▼                             ▼
        Класичні модулі LSM            Середовище BPF LSM
       (SELinux / AppArmor)          (eBPF Verifier та JIT)
                 │                             │
                 ▼                             ▼
         [Перевірка міток]            [Логіка програми eBPF]
                 │                    • Аналіз Inode виконуваного файлу
                 │                    • Перевірка ідентифікатора cgroup
                 │                    • Пошук за таблицями eBPF Map
                 │                             │
                 └──────────────┬──────────────┘
                                │
            Повернення 0 (Дозволено) або -EPERM / -EACCES (Заблоковано)

Щойно дія викликає спрацьовування хука безпеки (як-от security_socket_bind чи security_file_open), ядро призупиняє операцію, передає керування програмі eBPF та очікує код статусу. Значення 0 дозволяє виконання операції. Від'ємний код помилки (наприклад -EPERM) негайно блокує дію та повідомляє програмі користувача про відсутність доступу.

На відміну від пасивних засобів спостереження на зразок kprobes, підсистема BPF LSM ухвалює активні рішення щодо безпеки на апаратній швидкості із додатковою затримкою менше ніж 15 наносекунд на виклик.

Практична реалізація: налаштування програми BPF LSM

Наведений нижче приклад мовою C для eBPF розв'язує дві важливі задачі захисту: запобігання несанкціонованому перехопленню порту UDP та блокування читання пам'яті процесу VPN:

#include <vmlinux.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>

char LICENSE[] SEC("license") = "GPL";

#define EPERM 1
#define VPN_LISTENING_PORT 51820
#define VPN_BINARY_INODE 14829104

/* Таблиця eBPF із зареєстрованими ідентифікаторами процесів VPN */
struct {
    __uint(type, BPF_MAP_TYPE_HASH);
    __uint(max_entries, 64);
    __type(key, u32);
    __type(value, u8);
} authorized_vpn_pids SEC(".maps");

/* Захист 1: Дозвіл прив'язки до порту UDP лише авторизованому бінарному файлу */
SEC("lsm/socket_bind")
int BPF_PROG(restrict_vpn_bind, struct socket *sock, struct sockaddr *address, int addrlen)
{
    struct sockaddr_in *addr = (struct sockaddr_in *)address;
    
    if (addr->sin_family == AF_INET) {
        u16 port = __builtin_bswap16(addr->sin_port);
        
        if (port == VPN_LISTENING_PORT) {
            struct task_struct *task = (struct task_struct *)bpf_get_current_task();
            u64 inode = BPF_CORE_READ(task, mm, exe_file, f_inode, i_ino);
            
            /* Блокування, якщо inode процесу не збігається з файлом VPN */
            if (inode != VPN_BINARY_INODE) {
                bpf_printk("BPF LSM: Заблоковано спробу зайняти порт %d процесом з inode %lu\n", 
                           port, inode);
                return -EPERM;
            }
        }
    }
    return 0;
}

/* Захист 2: Заборона аналізу пам'яті та зневадження ptrace для процесів VPN */
SEC("lsm/ptrace_access_check")
int BPF_PROG(protect_vpn_memory, struct task_struct *child, unsigned int mode)
{
    u32 target_pid = BPF_CORE_READ(child, tgid);
    
    /* Перевірка, чи належить цільовий процес до зареєстрованих воркерів VPN */
    u8 *is_vpn = bpf_map_lookup_elem(&authorized_vpn_pids, &target_pid);
    if (is_vpn) {
        struct task_struct *caller = (struct task_struct *)bpf_get_current_task();
        u32 caller_pid = BPF_CORE_READ(caller, tgid);
        
        /* Заборона будь-якого стороннього втручання навіть за наявності UID 0 */
        if (caller_pid != target_pid) {
            bpf_printk("BPF LSM: Відбито спробу ptrace до процесу VPN %d від PID %d\n", 
                       target_pid, caller_pid);
            return -EPERM;
        }
    }
    return 0;
}

Скомпільований об'єктний модуль eBPF створює стійкий захисний бар'єр, що унеможливлює викрадення секретних ключів шифрування навіть у разі отримання зловмисником прав root на хості.

Порівняльний аналіз моделей контролю доступу

Відмінності в архітектурі BPF LSM та традиційних засобів розмежування прав пояснюють перехід сучасних платформ на програмовані механізми захисту:

Критерій оцінки Традиційна модель DAC Рішення SELinux / AppArmor Технологія Linux BPF LSM
Глибина розмежування Ідентифікатори UID та GID Матриця статичних міток Програмований аналіз Inode/PID/Cgroup
Захист від привілеїв root Відсутній (Root долає DAC) Високий (Контроль у ядрі) Високий (Root блокується хуками ядра)
Оновлення політик Миттєво (chmod) Потребує перезапуску служб Атомарне оновлення таблиць без простоїв
Оцінка контексту Базові атрибути файлів Мітки суб'єктів та об'єктів Детальний (IP, порти, контрольні суми)
Вплив на швидкодію CPU Незначний Зниження на 3% - 7% < 0.2% CPU (< 15 нс на один виклик)
Аудит та телеметрія Журнали Syslog / Auditd Події підсистеми Auditd Кільцеві буфери BPF RingBuffer і Prometheus

Завдяки збору повного контексту виконання та атомарному оновленню параметрів через мапи eBPF, підсистема BPF LSM усуває експлуатаційні недоліки, які раніше перешкоджали застосуванню мандатного контролю у динамічних інфраструктурах.

Практичне застосування в архітектурі RiceGuard Anycast

Інфраструктура RiceGuard використовує правила BPF LSM на прикордонних серверах мережі Anycast для ізоляції середовищ обробки трафіку:

  • Захищені криптографічні анклави: Підключення хуків BPF LSM до викликів security_file_open та security_ptrace_access_check забезпечує доступ до ключів Curve25519 та параметрів сесій лише верифікованому виконуваному файлу, унеможливлюючи дампи пам'яті.
  • Блокування перехоплення портів: Мережеві політики BPF LSM резервують робочі порти UDP на інтерфейсах сервера, негайно відкидаючи несанкціоновані запити на прив'язку сокетів від суміжних служб.
  • Запобігання витоку через простори імен: Механізм контролю сокетів перевіряє передавання дескрипторів між процесами, гарантуючи ізоляцію мережевих інтерфейсів між різними клієнтськими середовищами.

Поєднання верифікованих програм eBPF та перевіркових рубежів Linux Security Module формує надійний ешелон оборони для захисту конфіденційних даних безпосередньо на рівні ядра операційної системи.