Linux SIP прокси сервер: полное руководство по Kamailio, OpenSIPS и Asterisk

Полное руководство по настройке SIP прокси сервера на Linux.

SIP прокси сервер: установка Kamailio и OpenSIPS на Linux с нуля

Коротко: что делает SIP прокси
SIP прокси маршрутизирует SIP-сигнализацию между клиентами, не вмешиваясь в медиапоток. Он не транскодирует аудио и не пишет звонки. Его задача — умно переслать SIP-пакет туда, куда нужно. Для большинства задач: Kamailio на Debian, порт 5060, конфиг из этой статьи — и работает.

Диагноз: зачем ты здесь

Допустим, у тебя один из трёх сценариев.

Первый — односторонняя слышимость. Один слышит, второй нет. Виновник почти всегда NAT и отсутствие RTP-прокси. Второй — SIP-трафик идёт мимо твоего контроля. Провайдер, клиент, АТС — все общаются напрямую, а ты не видишь ни одного пакета. Третий — у тебя несколько АТС, и ты хочешь балансировать нагрузку между ними.

Во всех трёх случаях ответ — SIP прокси сервер.

Что получишь в итоге: работающий Kamailio или OpenSIPS на Debian/Ubuntu, настроенный outbound proxy, балансировку нагрузки, интеграцию с MikroTik и решение типовых проблем. Времени уйдёт 1-2 часа.

Что понадобится:

  • Сервер или VM с Debian 12 / Ubuntu 22.04
  • Root или sudo-доступ
  • Базовое понимание SIP (что такое INVITE, BYE, REGISTER)
  • Хотя бы один SIP-клиент для тестирования

Термины: что есть что

Половина проблем в VoIP начинается с того, что люди путают SIP proxy, B2BUA и SBC. Расставим точки.

Компонент Что делает Лезет в RTP? Примеры Когда нужен
SIP Proxy Маршрутизирует SIP-запросы Нет Kamailio, OpenSIPS Балансировка, масштаб
B2BUA Разрывает диалог на два Опционально Asterisk, FreeSWITCH АТС, IVR, запись
SBC Граница сетей + защита Да Kamailio + RTPengine Граница с оператором
Медиасервер Обработка RTP Да RTPengine, rtpproxy Конференции, транскодинг

Ключевое: SIP прокси не разрывает диалог. Два клиента общаются напрямую — прокси только направляет их. Как nginx для HTTP, только для SIP-сигнализации.

Asterisk — B2BUA. Он разрывает каждый SIP-диалог на два. Это не прокси, хотя многие руководства называют его именно так. Для небольших нагрузок сойдёт, но не путай термины.

Схема: как работает SIP прокси

%%{init: {
  'theme': 'base',
  'themeVariables': {
    'primaryColor': '#ffffff',
    'primaryTextColor': '#1e293b',
    'primaryBorderColor': '#94a3b8',
    'lineColor': '#64748b',
    'fontSize': '15px',
    'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
  },
  'flowchart': {'curve': 'linear', 'nodeSpacing': 50, 'rankSpacing': 50}
}}%%
flowchart TD
    A["SIP-клиент A"] -->|"INVITE"| P["SIP Proxy (Kamailio)"]
    P -->|"INVITE (forwarded)"| B["SIP-клиент B / АТС"]
    B -->|"200 OK"| P
    P -->|"200 OK"| A
    A -->|"RTP (напрямую)"| B
    B -->|"RTP (напрямую)"| A
    style A fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
    style P fill:#f8fafc,stroke:#f97316,stroke-width:2px,color:#9a3412
    style B fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d

Сигнализация идёт через прокси. Медиа (RTP) — напрямую между клиентами. Если RTP нужно тоже проксировать (NAT, запись) — подключаешь RTPengine.

Выбор решения

Kamailio — промышленный стандарт

Написан на C, 10 000+ звонков в секунду, модульная архитектура, используется Deutsche Telekom и сотней других операторов. Кривая обучения крутая — конфиг пишется на своём скриптовом языке. Но зато никаких ограничений.

Выбирай, если: высокая нагрузка, нужна гибкая маршрутизация, оператор связи, много кастомной логики.

OpenSIPS — когда нужен веб-интерфейс

Производительность сравнима с Kamailio. Есть встроенный Control Panel — управлять можно через браузер. Из коробки модули для биллинга и CDR. Чуть проще в первоначальной настройке.

Выбирай, если: средний бизнес, нужна балансировка и веб-управление, хочешь CDR без дополнительных интеграций.

Asterisk — для малого офиса

Все его знают. Для 50-100 абонентов хватит с запасом. Совмещает АТС и прокси в одном. Но не масштабируется и технически не является прокси — это B2BUA.

Выбирай, если: малый офис, уже стоит Asterisk, нагрузка небольшая.

Решение CPS RAM / 1000 звонков Веб Сложность
Kamailio 10 000+ ~500 MB Нет (Siremis отдельно) Высокая
OpenSIPS 10 000+ ~600 MB Да (Control Panel) Средняя
Asterisk ~1 000 ~200 MB Нет (FreePBX отдельно) Низкая
FreeSWITCH 5 000+ ~800 MB Нет Средняя

Системные требования

Параметр Минимум Комфортно Продакшн (1000+ звонков)
CPU 1 ядро 2 ядра 4+ ядра
RAM 512 MB 2 GB 4-8 GB
Диск 10 GB 20 GB SSD 50+ GB SSD (логи)
Сеть 100 Мбит 1 Гбит 1 Гбит, 2 интерфейса
ОС Debian 11 Debian 12 Debian 12 / Ubuntu 22.04

На момент публикации актуален Kamailio 5.8.x и OpenSIPS 3.4.x. Перед установкой проверь актуальные релизы на официальных сайтах.

Подготовка системы

Обновление и базовые пакеты

Начинаем с чистой Debian 12. Обновляемся, ставим инструменты диагностики — они пригодятся:


apt update && apt upgrade -y

apt install -y curl wget git vim net-tools tcpdump ngrep \
  iptables-persistent fail2ban build-essential sngrep

sngrep поставь сразу — это интерактивный монитор SIP-трафика. Сэкономит часы отладки.

Оптимизация ядра для SIP-нагрузки

SIP генерирует много коротких UDP-сессий. Без оптимизации ядро начнёт захлёбываться раньше, чем Kamailio:


nano /etc/sysctl.conf

# Увеличение очередей соединений
net.core.somaxconn = 4096
net.core.netdev_max_backlog = 5000
net.ipv4.tcp_max_syn_backlog = 8096

# Быстрое освобождение TIME_WAIT
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_tw_reuse = 1

# Диапазон локальных портов (важно для RTP)
net.ipv4.ip_local_port_range = 10000 65535

# UDP буферы
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.udp_mem = 8388608 12582912 16777216

sysctl -p

Таблица портов SIP-инфраструктуры

Порт Протокол Назначение Обязательный?
5060 UDP / TCP SIP сигнализация Да
5061 TCP SIP TLS (SIPS) Если нужен TLS
10000-20000 UDP RTP медиапоток Если проксируешь медиа
2223 UDP RTPengine управление Если ставишь RTPengine
8080 TCP Kamailio XMLRPC/HTTP API Для мониторинга

Базовый файрвол

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

# Разрешаем loopback
iptables -A INPUT -i lo -j ACCEPT

# Разрешаем установленные соединения
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# SSH
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# SIP сигнализация
iptables -A INPUT -p udp --dport 5060 -j ACCEPT
iptables -A INPUT -p tcp --dport 5060 -j ACCEPT

# SIP TLS
iptables -A INPUT -p tcp --dport 5061 -j ACCEPT

# RTP (если нужен RTPengine)
iptables -A INPUT -p udp --dport 10000:20000 -j ACCEPT

# Всё остальное - дропаем
iptables -A INPUT -j DROP

# Сохраняем
netfilter-persistent save

Установка и настройка Kamailio на Debian

Установка пакетов


# Добавляем официальный репозиторий
wget -O- https://deb.kamailio.org/kamailiodebkey.gpg | apt-key add -
echo "deb https://deb.kamailio.org/kamailio58 bookworm main" > /etc/apt/sources.list.d/kamailio.list

apt update

# Ставим Kamailio с нужными модулями
apt install -y kamailio kamailio-mysql-modules kamailio-tls-modules \
  kamailio-websocket-modules kamailio-utils-modules kamailio-json-modules

# Проверяем версию
kamailio -v

Ожидаемый вывод: version: kamailio 5.8.x. Если видишь что-то другое — проверь, правильный ли репозиторий добавился.

Структура конфигурации

Главный файл: /etc/kamailio/kamailio.cfg. Состоит из трёх блоков:

Первый — глобальные параметры: порты, IP, количество дочерних процессов. Второй — подключение модулей и их настройки. Третий — routing blocks, то есть логика обработки SIP-сообщений. Именно здесь описывается, что делать с каждым INVITE, REGISTER, BYE.

Минимальный рабочий конфиг — stateless proxy

Делаем бэкап и пишем конфиг с нуля:


cp /etc/kamailio/kamailio.cfg /etc/kamailio/kamailio.cfg.orig
nano /etc/kamailio/kamailio.cfg

####### Global Parameters #########

debug=2
log_stderror=no
log_facility=LOG_LOCAL0
fork=yes
children=4

# Слушаем на всех интерфейсах
listen=udp:0.0.0.0:5060
listen=tcp:0.0.0.0:5060

# DNS отключаем пока (включим позже)
disable_dns_failover=yes
dns=no
rev_dns=no

####### Modules Section ########

loadmodule "sl.so"       # Stateless replies
loadmodule "tm.so"       # Transaction management
loadmodule "rr.so"       # Record-Route (обязательно!)
loadmodule "maxfwd.so"   # Max-Forward check (защита от петель)
loadmodule "textops.so"  # Text operations
loadmodule "siputils.so" # SIP utilities

# Таймауты транзакций
modparam("tm", "fr_timer", 30000)
modparam("tm", "fr_inv_timer", 120000)

####### Routing Logic ########

request_route {

    # Защита от петель маршрутизации
    if (!mf_process_maxfwd_header("10")) {
        sl_send_reply("483", "Too Many Hops");
        exit;
    }

    xlog("L_INFO", "SIP Request: $rm from $fu to $tu via $si\n");

    # Record-Route: без этого BYE пойдёт мимо прокси
    if (method=="INVITE" || method=="SUBSCRIBE") {
        record_route();
    }

    # Loose route: обработка последующих запросов в диалоге
    if (loose_route()) {
        xlog("L_INFO", "Loose route - forwarding\n");
        t_relay();
        exit;
    }

    if (method=="REGISTER") {
        xlog("L_INFO", "REGISTER from $fu\n");
        t_relay();
        exit;
    }

    if (method=="INVITE") {
        xlog("L_INFO", "INVITE from $fu to $ru\n");
        t_relay();
        exit;
    }

    t_relay();
}

onreply_route {
    xlog("L_INFO", "SIP Reply: $rs $rr\n");
}

failure_route {
    xlog("L_INFO", "Transaction failed: $rm to $ru\n");
}

Запуск и проверка


# Проверка синтаксиса (обязательно перед запуском)
kamailio -c -f /etc/kamailio/kamailio.cfg

# Если ошибок нет - запускаем
systemctl start kamailio
systemctl enable kamailio

# Проверяем статус
systemctl status kamailio

# Смотрим логи в реальном времени
tail -f /var/log/syslog | grep kamailio

Что должно быть в логах после старта:


kamailio[PID]: INFO: core [main.c]: main_loop: started
kamailio[PID]: INFO: listening on udp: 0.0.0.0:5060

Если видишь эти строки — Kamailio слушает. Проверяем:


netstat -tulnp | grep 5060
# Должно показать: udp 0 0 0.0.0.0:5060  LISTEN  kamailio

Record-Route и Loose Route — это важно

Вот тут большинство и облажается. Поясню один раз.

Когда Kamailio обрабатывает INVITE, он добавляет заголовок Record-Route со своим адресом. Это сигнал клиентам: все последующие запросы в этом диалоге (BYE, re-INVITE) должны идти через меня.

Без record_route() — клиент A и клиент B после INVITE начнут общаться напрямую. BYE уйдёт мимо прокси. Ты потеряешь контроль над диалогом.

loose_route() — обработка запросов, которые уже содержат Route-заголовок. Это как раз те самые последующие BYE и re-INVITE. Без этого блока они будут падать с ошибкой.


# Упрощённо: как это выглядит в SIP-трейсе
INVITE sip:bob@example.com SIP/2.0
Via: SIP/2.0/UDP client-a:5060
...

# Kamailio добавляет:
Record-Route: <sip:192.168.1.50:5060;lr>

# Ответ 200 OK содержит Contact клиента B
# Последующий BYE от A идёт через Route: <sip:192.168.1.50:5060;lr>
# Kamailio обрабатывает его через loose_route() и пересылает B

Это не опция — это обязательная конструкция в каждом конфиге SIP прокси.

Настройка Outbound SIP Proxy

Outbound proxy — это когда все SIP-запросы клиента принудительно идут через твой сервер, независимо от того, что написано в Request-URI.

Нужен для: контроля трафика, логирования, применения политик, NAT traversal.

Как настраивается на стороне клиента

В большинстве SIP-клиентов (Zoiper, MicroSIP, Linphone):

  • Outbound Proxy: sip:IP-твоего-сервера:5060
  • Force Outbound Proxy: включить

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

Маршрутизация на стороне Kamailio

Добавь в request_route после проверки Max-Forwards:


if (method=="INVITE" && !has_totag()) {

    record_route();

    xlog("L_INFO", "Outbound INVITE from $fu to $ru via $si\n");

    # Номера на 8 - провайдер А
    if ($rU =~ "^8") {
        $ru = "sip:" + $rU + "@provider-a.com";
        t_relay();
        exit;
    }

    # Всё остальное - провайдер Б
    $ru = "sip:" + $rU + "@provider-b.com";
    t_relay();
    exit;
}

!has_totag() — проверка, что это первый INVITE, а не re-INVITE внутри уже установленного диалога. Без этой проверки маршрутизация применится и к re-INVITE, что сломает перевод звонков.

Схема: outbound proxy в действии

%%{init: {
  'theme': 'base',
  'themeVariables': {
    'primaryColor': '#ffffff',
    'primaryTextColor': '#1e293b',
    'primaryBorderColor': '#94a3b8',
    'lineColor': '#64748b',
    'fontSize': '15px',
    'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
  },
  'flowchart': {'curve': 'linear', 'nodeSpacing': 50, 'rankSpacing': 50}
}}%%
flowchart TD
    C["SIP-клиент"] -->|"все запросы"| P["Kamailio Outbound Proxy"]
    P -->|"8xxx"| PA["Провайдер A"]
    P -->|"7xxx"| PB["Провайдер B"]
    P -->|"внутренние"| AS["Asterisk АТС"]
    style C fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
    style P fill:#f8fafc,stroke:#f97316,stroke-width:2px,color:#9a3412
    style PA fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
    style PB fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
    style AS fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d

OpenSIPS: балансировка нагрузки между АТС

Если нужно распределять звонки между несколькими серверами — OpenSIPS с модулем dispatcher делает это нативно.

Установка OpenSIPS


apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 049AD65B
echo "deb https://apt.opensips.org bookworm 3.4-releases" > /etc/apt/sources.list.d/opensips.list
apt update
apt install -y opensips opensips-mysql-module opensips-tls-module

opensips -V

Конфиг Dispatcher для балансировки


loadmodule "dispatcher.so"

modparam("dispatcher", "db_url", "mysql://opensips:password@localhost/opensips")
modparam("dispatcher", "table_name", "dispatcher")
modparam("dispatcher", "flags", 2)
modparam("dispatcher", "dst_avp", "$avp(ds_dst)")
modparam("dispatcher", "grp_avp", "$avp(ds_grp)")
modparam("dispatcher", "cnt_avp", "$avp(ds_cnt)")

# Проверка доступности серверов через OPTIONS
modparam("dispatcher", "ds_ping_interval", 30)
modparam("dispatcher", "ds_probing_mode", 1)

route {
    if (method=="INVITE") {
        # round-robin балансировка по группе 1
        if (!ds_select_dst("1", "4")) {
            send_reply("503", "Service Unavailable");
            exit;
        }

        xlog("L_INFO", "Dispatched to $du\n");
        record_route();
        t_relay();
        exit;
    }
}

failure_route[1] {
    # Сервер не ответил - пробуем следующий
    if (t_check_status("408|503")) {
        if (ds_next_dst()) {
            xlog("L_INFO", "Trying next: $du\n");
            t_relay();
            exit;
        }
    }
}

Добавляем серверы в базу:


mysql -u opensips -p opensips

INSERT INTO dispatcher (setid, destination, flags, description) VALUES
(1, 'sip:192.168.1.10:5060', 0, 'Asterisk-1'),
(1, 'sip:192.168.1.11:5060', 0, 'Asterisk-2'),
(1, 'sip:192.168.1.12:5060', 0, 'Asterisk-3');

# Перезагружаем список серверов без рестарта
opensipsctl fifo ds_reload

Алгоритм 4 — round-robin. Если нужна балансировка по весу — используй алгоритм 6 (weighted round-robin). Все доступные алгоритмы смотри в документации модуля dispatcher.

Asterisk для малого офиса

Для 50-100 абонентов можно не городить Kamailio. Asterisk справится.


apt install -y asterisk
# Или последнюю версию из исходников
cd /usr/src
wget https://downloads.asterisk.org/pub/telephony/asterisk/asterisk-20-current.tar.gz
tar xvf asterisk-20-current.tar.gz
cd asterisk-20*/
./configure && make menuselect && make && make install

Минимальный PJSIP конфиг для пересылки звонков:


[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0:5060

[provider-trunk]
type=endpoint
context=from-provider
disallow=all
allow=ulaw,alaw
direct_media=no
rtp_symmetric=yes
force_rport=yes

; extensions.conf
[default]
exten => _X.,1,NoOp(Proxy call to ${EXTEN})
exten => _X.,n,Dial(PJSIP/${EXTEN}@provider-trunk,,r)
exten => _X.,n,Hangup()

direct_media=no означает, что RTP идёт через Asterisk. Это не чистый прокси, но для малого офиса разница несущественна.

Интеграция с MikroTik

MikroTik и SIP — отдельная история. Встроенный SIP ALG чаще вредит, чем помогает. Правильная схема: MikroTik пробрасывает порты, Kamailio обрабатывает всё остальное.

Отключить SIP ALG на MikroTik


/ip firewall service-port set sip disabled=yes

Да, именно отключить. SIP ALG переписывает заголовки и ломает NAT traversal. Пусть Kamailio разбирается с NAT сам.

Проброс портов на Kamailio


# SIP UDP
/ip firewall nat add chain=dstnat protocol=udp dst-port=5060 \
  action=dst-nat to-addresses=192.168.1.50 to-ports=5060 \
  comment="SIP to Kamailio"

# SIP TCP
/ip firewall nat add chain=dstnat protocol=tcp dst-port=5060 \
  action=dst-nat to-addresses=192.168.1.50 to-ports=5060

# RTP диапазон (если используешь RTPengine)
/ip firewall nat add chain=dstnat protocol=udp dst-port=10000-20000 \
  action=dst-nat to-addresses=192.168.1.50 to-ports=10000-20000 \
  comment="RTP to RTPengine"

Схема: MikroTik + Kamailio

%%{init: {
  'theme': 'base',
  'themeVariables': {
    'primaryColor': '#ffffff',
    'primaryTextColor': '#1e293b',
    'primaryBorderColor': '#94a3b8',
    'lineColor': '#64748b',
    'fontSize': '15px',
    'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
  },
  'flowchart': {'curve': 'linear', 'nodeSpacing': 50, 'rankSpacing': 50}
}}%%
flowchart TD
    I["Интернет / Провайдер"] -->|"порт 5060"| M["MikroTik (NAT)"]
    M -->|"dst-nat -> 192.168.1.50"| K["Kamailio SIP Proxy"]
    K -->|"SIP"| AS["Asterisk АТС"]
    K -->|"SIP"| PH["IP-телефоны"]
    K -->|"управление RTP"| RE["RTPengine"]
    RE -->|"медиапоток"| PH
    style I fill:#f8fafc,stroke:#94a3b8,stroke-width:2px,color:#475569
    style M fill:#f8fafc,stroke:#f97316,stroke-width:2px,color:#9a3412
    style K fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
    style AS fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
    style PH fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
    style RE fill:#f8fafc,stroke:#8b5cf6,stroke-width:2px,color:#5b21b6

Безопасность SIP прокси

SIP-серверы сканируются постоянно. На открытый порт 5060 начнут ломиться в первые же минуты после запуска. Это не паранойя — это реальность.

Fail2ban против брутфорса


nano /etc/fail2ban/filter.d/kamailio.conf

[Definition]
failregex = kamailio.*authentication failure.*
            kamailio.*407 Proxy Authentication Required.*
            kamailio.*401 Unauthorized.*
ignoreregex =

nano /etc/fail2ban/jail.local

[kamailio]
enabled = true
port = 5060,5061
protocol = udp
filter = kamailio
logpath = /var/log/syslog
maxretry = 5
bantime = 3600
findtime = 600

systemctl restart fail2ban
fail2ban-client status kamailio

Pike — защита от SIP-флуда

Fail2ban работает по логам с задержкой. Pike — модуль Kamailio, который режет флуд в реальном времени:


loadmodule "pike.so"

modparam("pike", "sampling_time_unit", 2)
modparam("pike", "reqs_density_per_unit", 30)
modparam("pike", "remove_latency", 120)

# В начале request_route:
if (!pike_check_req()) {
    xlog("L_ALERT", "PIKE: flood from $si - dropping\n");
    exit;
}

30 запросов за 2 секунды с одного IP — блокируем на 120 секунд. Для легитимных клиентов этого не заметно, для сканеров — стена.

IP Whitelist для доверенных источников


# Только свои IP - остальным 403
if ($si != "192.168.1.0/24" && $si != "10.0.0.50") {
    sl_send_reply("403", "Forbidden");
    exit;
}

Если у тебя VoIP-провайдер с фиксированными IP — добавь их в whitelist. Все остальные пусть идут лесом.

TLS для шифрования сигнализации


# Самоподписанный сертификат (для продакшна используй Let's Encrypt)
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout /etc/kamailio/kamailio.key \
  -out /etc/kamailio/kamailio.crt

nano /etc/kamailio/tls.cfg

[server:default]
method = TLSv1.2+
verify_certificate = no
require_certificate = no
private_key = /etc/kamailio/kamailio.key
certificate = /etc/kamailio/kamailio.crt

# В kamailio.cfg добавь:
loadmodule "tls.so"
modparam("tls", "config", "/etc/kamailio/tls.cfg")
listen=tls:0.0.0.0:5061

Мониторинг SIP-прокси

sngrep — интерактивный SIP-монитор

Это первый инструмент при любой проблеме. Показывает SIP-диалоги в реальном времени:


# Интерактивный режим
sngrep

# Фильтр по IP
sngrep host 192.168.1.100

# Только INVITE
sngrep -i "INVITE"

# Сохранить в PCAP для анализа в Wireshark
sngrep -O /tmp/sip-debug.pcap

В интерактивном режиме: стрелками выбирай диалог, Enter — подробности, F7 — фильтры.

Prometheus exporter для Kamailio


wget https://github.com/florentchauveau/kamailio_exporter/releases/latest/download/kamailio_exporter
chmod +x kamailio_exporter
mv kamailio_exporter /usr/local/bin/

nano /etc/systemd/system/kamailio_exporter.service

[Unit]
Description=Kamailio Prometheus Exporter
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/kamailio_exporter --kamailio.scrape-uri=http://localhost:8080/RPC2
Restart=on-failure

[Install]
WantedBy=multi-user.target

systemctl daemon-reload
systemctl enable --now kamailio_exporter
# Метрики: http://localhost:9494/metrics

Логирование в JSON для Grafana/Loki


# В kamailio.cfg
xlog("L_INFO", "{\"ts\":\"$TV(Sn)\", \"method\":\"$rm\", \"from\":\"$fu\", \"to\":\"$ru\", \"src\":\"$si\"}\n");

Настрой Promtail для чтения /var/log/syslog и парсинга JSON — получишь полную картину трафика в Grafana.

Устранение типовых проблем

Односторонняя слышимость

Симптом: один слышит, второй нет
Самая частая проблема в VoIP за NAT. Это не баг Kamailio — это отсутствие RTP-прокси. SIP-сигнализация прошла, а медиапоток упёрся в NAT и не дошёл.

Решение — поставить RTPengine:


apt install -y rtpengine

# В kamailio.cfg
loadmodule "rtpengine.so"
modparam("rtpengine", "rtpengine_sock", "udp:127.0.0.1:2223")

# В route для INVITE
if (method=="INVITE") {
    rtpengine_offer();
    record_route();
    t_relay();
}

# В onreply_route
onreply_route {
    if (status=="200" && has_body("application/sdp")) {
        rtpengine_answer();
    }
}

BYE и re-INVITE идут мимо прокси

Причина — забытый record_route(). Проверь, что он стоит для INVITE и SUBSCRIBE:


if (method=="INVITE" || method=="SUBSCRIBE") {
    record_route();
}

И что loose_route() обрабатывается до основной логики:


if (loose_route()) {
    t_relay();
    exit;
}

Kamailio не слушает на нужном IP


# Проверяем что слушает
netstat -tulnp | grep 5060
ss -tulnp | grep 5060

Если нужного IP нет — добавь в конфиг:


listen=udp:192.168.1.50:5060
listen=udp:10.0.0.50:5060
listen=tcp:0.0.0.0:5060

DNS не резолвится


# Проверяем резолв
dig provider.com SRV
dig _sip._udp.provider.com SRV
cat /etc/resolv.conf

В kamailio.cfg включи DNS:


dns=yes
rev_dns=yes

Ошибка «kamailio -c» при проверке конфига


kamailio -c -f /etc/kamailio/kamailio.cfg 2>&1 | head -30

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

Проверь, что все модули из loadmodule реально установлены:


dpkg -l | grep kamailio
ls /usr/lib/kamailio/modules/ | grep pike

TLS не поднимается


# Проверяем сертификат
openssl x509 -in /etc/kamailio/kamailio.crt -text -noout | grep -E "Subject|Not"

# Проверяем, что ключ совпадает с сертификатом
openssl x509 -noout -modulus -in kamailio.crt | md5sum
openssl rsa -noout -modulus -in kamailio.key | md5sum
# Хэши должны совпасть

Flood от провайдера или сканеров


# Смотрим кто атакует
tcpdump -i eth0 -n port 5060 | awk '{print $3}' | cut -d. -f1-4 | sort | uniq -c | sort -rn | head

# Блокируем конкретный IP через iptables
iptables -A INPUT -s 1.2.3.4 -j DROP

Если атаки регулярные — поставь Pike (описан выше) и настрой Fail2ban.

Резервное копирование

Что бэкапить:


# Конфиги Kamailio
tar czf /backup/kamailio-config-$(date +%Y%m%d).tar.gz /etc/kamailio/

# База данных (если используется MySQL)
mysqldump -u kamailio -p kamailio > /backup/kamailio-db-$(date +%Y%m%d).sql

# Автоматизация через cron
echo "0 3 * * * root tar czf /backup/kamailio-config-\$(date +\%Y\%m\%d).tar.gz /etc/kamailio/" >> /etc/crontab

Как восстановить:


# Восстановление конфига
tar xzf /backup/kamailio-config-20240101.tar.gz -C /

# Проверка синтаксиса после восстановления
kamailio -c -f /etc/kamailio/kamailio.cfg

# Рестарт
systemctl restart kamailio

Обновление Kamailio


# До обновления - бэкап
tar czf /backup/kamailio-before-update.tar.gz /etc/kamailio/

# Проверяем доступные версии
apt list --upgradable | grep kamailio

# Обновляем
apt update && apt upgrade kamailio

# Проверяем синтаксис после обновления
kamailio -c -f /etc/kamailio/kamailio.cfg

# Рестарт
systemctl restart kamailio

# Проверяем логи
tail -f /var/log/syslog | grep kamailio

Если что-то сломалось после обновления — откатываемся:


# Восстанавливаем конфиг
tar xzf /backup/kamailio-before-update.tar.gz -C /

# Откатываем пакет (если нужно)
apt install kamailio=5.7.x-1

Чек-лист перед запуском в продакшн

  • Debian 12 / Ubuntu 22.04 обновлён до актуальных пакетов
  • sysctl оптимизации применены и сохранены
  • Kamailio / OpenSIPS версия актуальная (5.8+ / 3.4+)
  • kamailio -c проходит без ошибок
  • record_route() стоит для INVITE и SUBSCRIBE
  • loose_route() обрабатывается в начале route
  • Файрвол настроен: 5060 UDP/TCP открыт, остальное закрыто
  • Fail2ban активен, jail для kamailio настроен
  • Pike модуль подключён для защиты от флуда
  • TLS сертификаты установлены (если нужен SIPS)
  • RTPengine поднят (если есть NAT-клиенты)
  • SIP ALG на MikroTik отключён
  • sngrep установлен, тестовый звонок проверен в трейсе
  • BYE после звонка проходит через прокси (проверь в sngrep)
  • Логирование настроено, ротация логов работает
  • Бэкап конфига настроен по крону
  • Схема сети и конфиги задокументированы

FAQ

Почему Kamailio, а не просто Asterisk?

Asterisk — B2BUA. Он разрывает каждый SIP-диалог на два независимых плеча. Это добавляет задержку, потребляет больше ресурсов и не масштабируется на высокие нагрузки. Kamailio работает как настоящий прокси — пересылает запросы без разрыва диалога. На одинаковом железе Kamailio обслуживает в 10 раз больше звонков. Для 50 абонентов разница несущественна. Для 5000 — принципиальна.

Как проверить, что Record-Route работает правильно?

Запусти sngrep, сделай тестовый звонок и посмотри на трейс. В INVITE должен быть заголовок Record-Route с IP твоего прокси. В последующем BYE должен быть заголовок Route с тем же адресом. Если BYE идёт напрямую между клиентами — record_route не работает.


# Быстрая проверка в логах
grep "BYE" /var/log/syslog | grep kamailio
# Если строки есть - BYE проходит через прокси

Что если провайдер не принимает INVITE через прокси?

Провайдер смотрит на From-header и Contact. Если там IP внутреннего клиента вместо IP прокси — он отвергает запрос. Решение — UAC Replace в Kamailio:


loadmodule "uac.so"

# Заменяем From на наш внешний IP
uac_replace_from("", "sip:$fU@твой-внешний-IP");

Почему SIP ALG на MikroTik надо отключать?

SIP ALG пытается помочь с NAT: переписывает IP-адреса в SIP-заголовках. Но делает это неправильно в 90% случаев: ломает Via-заголовки, портит Contact, создаёт дубли пакетов. Если у тебя стоит нормальный SIP прокси с RTPengine — ALG только мешает. Отключай сразу.

Как балансировать не по round-robin, а по нагрузке?

В OpenSIPS dispatcher поддерживает несколько алгоритмов. Алгоритм 10 — балансировка по нагрузке на основе активных звонков. Нужен модуль load_balancer вместо dispatcher или совместное использование. Алгоритм 8 в dispatcher — weighted random, распределение по весам из базы.

Как откатиться, если конфиг сломал всё?


# Восстанавливаем бэкап конфига
cp /etc/kamailio/kamailio.cfg.orig /etc/kamailio/kamailio.cfg

# Проверяем синтаксис
kamailio -c -f /etc/kamailio/kamailio.cfg

# Перезапускаем
systemctl restart kamailio

Именно поэтому бэкап перед любым изменением — не опция, а обязательный шаг.

Итог

У тебя теперь есть всё для запуска SIP прокси в продакшне: понимание архитектуры, рабочие конфиги Kamailio и OpenSIPS, интеграция с MikroTik, защита от атак и решение типовых проблем.

Три главных вещи, которые реально важны:

Первое — record_route() обязателен. Без него ты не контролируешь диалог после INVITE. Второе — SIP ALG на MikroTik отключи сразу. Третье — если есть NAT-клиенты, RTPengine нужен с самого начала, не после того как пользователи начнут жаловаться.

Начни с простого stateless proxy, убедись что понимаешь трейс в sngrep, потом добавляй RTPengine и балансировку. Не пытайся сразу построить идеальную систему — сначала сделай работающую.

Не заработало?
Пиши в комментарии. Прикладывай вывод sngrep или фрагмент логов — разберём. Без этого диагностировать что-то по описанию «не работает» — занятие неблагодарное.
Андрей Анатольевич
Author: Андрей Анатольевич

Руководитель ИТ / Кризис-менеджер 25 лет в IT: от инженера в МегаФоне до руководителя отдела. Знаю, как выглядит бардак: нестабильные сети, устаревшая инфраструктура, конфликты в команде, раздутые сроки. Помогаю бизнесу выходить из кризиса: навожу порядок в легаси, стабилизирую то, что разваливается, выстраиваю прогнозируемые процессы. Не раз возвращал к жизни ИТ-структуры — знаю цену хаосу. 📍 Ищу проект для полной реорганизации / стабилизации. 📬 Telegram: @over_dude ✉️ mail@it-apteka.com

Оставайтесь на связи

Рецепты от IT-боли. Без воды, без рекламы, без маркетинговой шелухи.

Подписаться на IT-Аптеку →

Мы ВКонтакте

IT-Аптека — советы, новости и помощь рядом.

Вступить в группу ВКонтакте →
Поделитесь:

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Прокрутить вверх