<h1>SIP прокси сервер: установка Kamailio и OpenSIPS на Linux с нуля</h1>
"Коротко:
<br />
SIP прокси маршрутизирует SIP-сигнализацию между клиентами, не вмешиваясь в медиапоток. Он не транскодирует аудио и не пишет звонки. Его задача — умно переслать SIP-пакет туда, куда нужно. Для большинства задач: Kamailio на <a class="wpil_keyword_link" title="Debian" href="https://it-apteka.com/tag/debian/" target="_blank" rel="noopener" data-wpil-keyword-link="linked" data-wpil-monitor-id="1706">Debian</a>, порт 5060, конфиг из этой статьи — и работает.<br />
<h2>Диагноз: зачем ты здесь</h2>
<p>Допустим, у тебя один из трёх сценариев.</p>
<p>Первый — односторонняя слышимость. Один слышит, второй нет. Виновник почти всегда NAT и отсутствие RTP-прокси. Второй — SIP-трафик идёт мимо твоего контроля. Провайдер, клиент, АТС — все общаются напрямую, а ты не видишь ни одного пакета. Третий — у тебя несколько АТС, и ты хочешь балансировать нагрузку между ними.</p>
<p>Во всех трёх случаях ответ — SIP прокси сервер.</p>
<p><strong>Что получишь в итоге:</strong> работающий Kamailio или OpenSIPS на Debian/Ubuntu, настроенный outbound proxy, балансировку нагрузки, интеграцию с MikroTik и решение типовых проблем. Времени уйдёт 1-2 часа.</p>
<p><strong>Что понадобится:</strong></p>
<ul>
<li>Сервер или VM с Debian 12 / <a title="Какой VPN сервер установить на Ubuntu для нативного подключения" href="https://it-apteka.com/kakoj-vpn-server-ustanovit-na-ubuntu-dlja-nativnogo-podkljuchenija/" target="_blank" rel="noopener" data-wpil-monitor-id="1709">Ubuntu</a> 22.04</li>
<li>Root или sudo-доступ</li>
<li>Базовое понимание SIP (что такое INVITE, BYE, REGISTER)</li>
<li>Хотя бы один SIP-клиент для тестирования</li>
</ul>
<h2>Термины: что есть что</h2>
<p>Половина проблем в VoIP начинается с того, что люди путают SIP proxy, B2BUA и SBC. Расставим точки.</p>
<table style="border-collapse: collapse; width: 100%;" border="1" cellspacing="0" cellpadding="8">
<thead>
<tr style="background-color: #f0f0f0;">
<th>Компонент</th>
<th>Что делает</th>
<th>Лезет в RTP?</th>
<th>Примеры</th>
<th>Когда нужен</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>SIP Proxy</strong></td>
<td>Маршрутизирует SIP-запросы</td>
<td>Нет</td>
<td>Kamailio, OpenSIPS</td>
<td>Балансировка, масштаб</td>
</tr>
<tr>
<td><strong>B2BUA</strong></td>
<td>Разрывает диалог на два</td>
<td>Опционально</td>
<td>Asterisk, FreeSWITCH</td>
<td>АТС, IVR, запись</td>
</tr>
<tr>
<td><strong>SBC</strong></td>
<td>Граница сетей + защита</td>
<td>Да</td>
<td>Kamailio + RTPengine</td>
<td>Граница с оператором</td>
</tr>
<tr>
<td><strong>Медиасервер</strong></td>
<td>Обработка RTP</td>
<td>Да</td>
<td>RTPengine, rtpproxy</td>
<td>Конференции, транскодинг</td>
</tr>
</tbody>
</table>
<p><strong>Ключевое:</strong> SIP прокси не разрывает диалог. Два клиента общаются напрямую — прокси только направляет их. Как nginx для HTTP, только для SIP-сигнализации.</p>
<p>Asterisk — B2BUA. Он разрывает каждый SIP-диалог на два. Это не прокси, хотя многие руководства называют его именно так. Для небольших нагрузок сойдёт, но не путай термины.</p>
<h3>Схема: как работает SIP прокси</h3>
<pre class="mermaid">%%{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
</pre>
<p>Сигнализация идёт через прокси. Медиа (RTP) — напрямую между клиентами. Если RTP нужно тоже проксировать (NAT, запись) — подключаешь RTPengine.</p>
<h2>Выбор решения</h2>
<h3>Kamailio — промышленный стандарт</h3>
<p>Написан на C, 10 000+ звонков в секунду, модульная архитектура, используется Deutsche Telekom и сотней других операторов. Кривая обучения крутая — конфиг пишется на своём скриптовом языке. Но зато никаких ограничений.</p>
<p>Выбирай, если: высокая нагрузка, нужна гибкая маршрутизация, оператор связи, много кастомной логики.</p>
<h3>OpenSIPS — когда нужен веб-интерфейс</h3>
<p>Производительность сравнима с Kamailio. Есть встроенный Control Panel — управлять можно через браузер. Из коробки модули для биллинга и CDR. Чуть проще в первоначальной настройке.</p>
<p>Выбирай, если: средний бизнес, нужна балансировка и веб-управление, хочешь CDR без дополнительных интеграций.</p>
<h3>Asterisk — для малого офиса</h3>
<p>Все его знают. Для 50-100 абонентов хватит с запасом. Совмещает АТС и прокси в одном. Но не масштабируется и технически не является прокси — это B2BUA.</p>
<p>Выбирай, если: малый офис, уже стоит Asterisk, нагрузка небольшая.</p>
<table style="border-collapse: collapse; width: 100%;" border="1" cellspacing="0" cellpadding="8">
<thead>
<tr style="background-color: #f0f0f0;">
<th>Решение</th>
<th>CPS</th>
<th>RAM / 1000 звонков</th>
<th>Веб</th>
<th>Сложность</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Kamailio</strong></td>
<td>10 000+</td>
<td>~500 MB</td>
<td>Нет (Siremis отдельно)</td>
<td>Высокая</td>
</tr>
<tr>
<td><strong>OpenSIPS</strong></td>
<td>10 000+</td>
<td>~600 MB</td>
<td>Да (Control Panel)</td>
<td>Средняя</td>
</tr>
<tr>
<td><strong>Asterisk</strong></td>
<td>~1 000</td>
<td>~200 MB</td>
<td>Нет (FreePBX отдельно)</td>
<td>Низкая</td>
</tr>
<tr>
<td><strong>FreeSWITCH</strong></td>
<td>5 000+</td>
<td>~800 MB</td>
<td>Нет</td>
<td>Средняя</td>
</tr>
</tbody>
</table>
<h2>Системные требования</h2>
<table style="border-collapse: collapse; width: 100%;" border="1" cellspacing="0" cellpadding="8">
<thead>
<tr style="background-color: #f0f0f0;">
<th>Параметр</th>
<th>Минимум</th>
<th>Комфортно</th>
<th>Продакшн (1000+ звонков)</th>
</tr>
</thead>
<tbody>
<tr>
<td>CPU</td>
<td>1 ядро</td>
<td>2 ядра</td>
<td>4+ ядра</td>
</tr>
<tr>
<td>RAM</td>
<td>512 MB</td>
<td>2 GB</td>
<td>4-8 GB</td>
</tr>
<tr>
<td>Диск</td>
<td>10 GB</td>
<td>20 GB <a class="wpil_keyword_link" title="ssd" href="https://it-apteka.com/tag/ssd/" target="_blank" rel="noopener" data-wpil-keyword-link="linked" data-wpil-monitor-id="1708">SSD</a></td>
<td>50+ GB SSD (логи)</td>
</tr>
<tr>
<td>Сеть</td>
<td>100 Мбит</td>
<td>1 Гбит</td>
<td>1 Гбит, 2 интерфейса</td>
</tr>
<tr>
<td>ОС</td>
<td>Debian 11</td>
<td>Debian 12</td>
<td><a title="Настройка статического IP в Ubuntu 22.04-24.04 и Debian 12-13: Новый мир Netplan" href="https://it-apteka.com/nastrojka-staticheskogo-ip-v-ubuntu-22-04-24-04-i-debian-12-13-nov/" target="_blank" rel="noopener" data-wpil-monitor-id="1714">Debian 12 / Ubuntu</a> 22.04</td>
</tr>
</tbody>
</table>
<p>На момент публикации актуален Kamailio 5.8.x и OpenSIPS 3.4.x. Перед <a title="Установка Joomla: пошаговый рецепт от нуля до рабочего сайта" href="https://it-apteka.com/ustanovka-joomla-poshagovyj-recept-ot-nulja-do-rabochego-sajta/" target="_blank" rel="noopener" data-wpil-monitor-id="1710">установкой проверь актуальные релизы на официальных сайтах</a>.</p>
<h2>Подготовка системы</h2>
<h3>Обновление и базовые пакеты</h3>
<p>Начинаем с чистой Debian 12. Обновляемся, ставим инструменты диагностики — они пригодятся:</p>
<pre><code class="language-bash">
apt update && apt upgrade -y
apt install -y curl wget git vim net-tools tcpdump ngrep \
iptables-persistent fail2ban build-essential sngrep
</code></pre>
<p><code>sngrep</code> поставь сразу — это интерактивный монитор SIP-трафика. Сэкономит часы отладки.</p>
<h3>Оптимизация ядра для SIP-нагрузки</h3>
<p>SIP генерирует много коротких UDP-сессий. Без оптимизации ядро начнёт захлёбываться раньше, чем Kamailio:</p>
<pre><code class="language-bash">
nano /etc/sysctl.conf
</code></pre>
<pre><code class="language-text">
# Увеличение очередей соединений
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
</code></pre>
<pre><code class="language-bash">
sysctl -p
</code></pre>
<h3>Таблица портов SIP-инфраструктуры</h3>
<table style="border-collapse: collapse; width: 100%;" border="1" cellspacing="0" cellpadding="8">
<thead>
<tr style="background-color: #f0f0f0;">
<th>Порт</th>
<th>Протокол</th>
<th>Назначение</th>
<th>Обязательный?</th>
</tr>
</thead>
<tbody>
<tr>
<td>5060</td>
<td>UDP / TCP</td>
<td>SIP сигнализация</td>
<td>Да</td>
</tr>
<tr>
<td>5061</td>
<td>TCP</td>
<td>SIP TLS (SIPS)</td>
<td>Если нужен TLS</td>
</tr>
<tr>
<td>10000-20000</td>
<td>UDP</td>
<td>RTP медиапоток</td>
<td>Если проксируешь медиа</td>
</tr>
<tr>
<td>2223</td>
<td>UDP</td>
<td>RTPengine управление</td>
<td>Если ставишь RTPengine</td>
</tr>
<tr>
<td>8080</td>
<td>TCP</td>
<td>Kamailio XMLRPC/HTTP API</td>
<td>Для мониторинга</td>
</tr>
</tbody>
</table>
<h3>Базовый файрвол</h3>
"Осторожно
<br />
Не закрывай SSH до того, как убедишься, что правило для порта 22 добавлено. Иначе потеряешь доступ к серверу.<br />
<pre><code class="language-bash">
# Разрешаем 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
</code></pre>
<h2>Установка и настройка Kamailio на Debian</h2>
<h3>Установка пакетов</h3>
<pre><code class="language-bash">
# Добавляем официальный репозиторий
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
</code></pre>
<p>Ожидаемый вывод: <code>version: kamailio 5.8.x</code>. Если видишь что-то другое — проверь, правильный ли репозиторий добавился.</p>
<h3>Структура конфигурации</h3>
<p>Главный файл: <code>/etc/kamailio/kamailio.cfg</code>. Состоит из трёх блоков:</p>
<p>Первый — глобальные параметры: порты, IP, количество дочерних процессов. Второй — подключение модулей и их настройки. Третий — routing blocks, то есть логика обработки SIP-сообщений. Именно здесь описывается, что делать с каждым INVITE, REGISTER, BYE.</p>
<h3>Минимальный рабочий конфиг — stateless proxy</h3>
<p>Делаем бэкап и пишем конфиг с нуля:</p>
<pre><code class="language-bash">
cp /etc/kamailio/kamailio.cfg /etc/kamailio/kamailio.cfg.orig
nano /etc/kamailio/kamailio.cfg
</code></pre>
<pre><code class="language-text">
####### 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");
}
</code></pre>
<h3>Запуск и проверка</h3>
<pre><code class="language-bash">
# Проверка синтаксиса (обязательно перед запуском)
kamailio -c -f /etc/kamailio/kamailio.cfg
# Если ошибок нет - запускаем
systemctl start kamailio
systemctl enable kamailio
# Проверяем статус
systemctl status kamailio
# Смотрим логи в реальном времени
tail -f /var/log/syslog | grep kamailio
</code></pre>
<p>Что должно быть в логах после старта:</p>
<pre><code class="language-text">
kamailio[PID]: INFO: core [main.c]: main_loop: started
kamailio[PID]: INFO: listening on udp: 0.0.0.0:5060
</code></pre>
<p>Если видишь эти строки — Kamailio слушает. Проверяем:</p>
<pre><code class="language-bash">
netstat -tulnp | grep 5060
# Должно показать: udp 0 0 0.0.0.0:5060 LISTEN kamailio
</code></pre>
<h2>Record-Route и Loose Route — это важно</h2>
<p>Вот тут большинство и облажается. Поясню один раз.</p>
<p>Когда Kamailio обрабатывает INVITE, он добавляет заголовок <code>Record-Route</code> со своим адресом. Это сигнал клиентам: все последующие запросы в этом диалоге (BYE, re-INVITE) должны идти через меня.</p>
<p>Без <code>record_route()</code> — клиент A и клиент B после INVITE начнут общаться напрямую. BYE уйдёт мимо прокси. Ты потеряешь контроль над диалогом.</p>
<p><code>loose_route()</code> — обработка запросов, которые уже содержат Route-заголовок. Это как раз те самые последующие BYE и re-INVITE. Без этого блока они будут падать с ошибкой.</p>
<pre><code class="language-text">
# Упрощённо: как это выглядит в 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
</code></pre>
<p>Это не опция — это обязательная конструкция в каждом конфиге SIP прокси.</p>
<h2>Настройка Outbound SIP Proxy</h2>
<p>Outbound proxy — это когда все SIP-запросы <a title="VPN на MikroTik: полный гайд 2026 — WireGuard, L2TP/IPsec, IKEv2, настройка сервера и клиента" href="https://it-apteka.com/vpn-na-mikrotik-polnyj-gajd-2026-wireguard-l2tp-ipsec-ikev2-nastrojka-servera-i-klienta/" target="_blank" rel="noopener" data-wpil-monitor-id="1715">клиента принудительно идут через твой сервер</a>, независимо от того, что написано в Request-URI.</p>
<p>Нужен для: контроля трафика, логирования, применения политик, NAT traversal.</p>
<h3>Как настраивается на стороне клиента</h3>
<p>В большинстве SIP-клиентов (Zoiper, MicroSIP, Linphone):</p>
<ul>
<li><strong>Outbound Proxy:</strong> <code>sip:IP-твоего-сервера:5060</code></li>
<li><strong>Force Outbound Proxy:</strong> включить</li>
</ul>
<p>После этого все запросы клиента уходят на твой Kamailio, который решает, куда их дальше отправить.</p>
<h3>Маршрутизация на стороне Kamailio</h3>
<p>Добавь в <code>request_route</code> после проверки Max-Forwards:</p>
<pre><code class="language-text">
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;
}
</code></pre>
<p><code>!has_totag()</code> — проверка, что это первый INVITE, а не re-INVITE внутри уже установленного диалога. Без этой проверки маршрутизация применится и к re-INVITE, что сломает перевод звонков.</p>
<h3>Схема: outbound proxy в действии</h3>
<pre class="mermaid">%%{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
</pre>
<h2>OpenSIPS: балансировка нагрузки между АТС</h2>
<p>Если нужно распределять звонки между несколькими серверами — OpenSIPS с модулем dispatcher делает это нативно.</p>
<h3>Установка OpenSIPS</h3>
<pre><code class="language-bash">
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
</code></pre>
<h3>Конфиг Dispatcher для балансировки</h3>
<pre><code class="language-text">
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;
}
}
}
</code></pre>
<p>Добавляем <a href="https://it-apteka.com/mikrotik-chr-staticheskij-ip-dhcp-server-snat-i-marshrutizacija-cherez-proxmox/" target="_blank" rel="noopener" data-wpil-monitor-id="2073">серверы в базу:</a></p>
<pre><code class="language-bash">
mysql -u opensips -p opensips
</code></pre>
<pre><code class="language-sql">
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');
</code></pre>
<pre><code class="language-bash">
# Перезагружаем список серверов без рестарта
opensipsctl fifo ds_reload
</code></pre>
<p>Алгоритм <code>4</code> — round-robin. Если нужна балансировка по весу — используй алгоритм <code>6</code> (weighted round-robin). Все доступные алгоритмы смотри в документации модуля dispatcher.</p>
<h2>Asterisk для малого офиса</h2>
<p>Для 50-100 абонентов можно не городить Kamailio. Asterisk справится.</p>
<pre><code class="language-bash">
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
</code></pre>
<p>Минимальный PJSIP конфиг для пересылки звонков:</p>
<pre><code class="language-text">
[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
</code></pre>
<pre><code class="language-text">
; extensions.conf
[default]
exten => _X.,1,NoOp(Proxy call to ${EXTEN})
exten => _X.,n,Dial(PJSIP/${EXTEN}@provider-trunk,,r)
exten => _X.,n,Hangup()
</code></pre>
<p><code>direct_media=no</code> означает, что RTP идёт через Asterisk. Это не чистый прокси, но для малого офиса разница несущественна.</p>
<h2>Интеграция с MikroTik</h2>
<p>MikroTik и SIP — отдельная история. Встроенный SIP ALG чаще вредит, чем помогает. Правильная схема: MikroTik пробрасывает порты, Kamailio обрабатывает всё остальное.</p>
<h3>Отключить SIP ALG на MikroTik</h3>
<pre><code class="language-bash">
/ip firewall service-port set sip disabled=yes
</code></pre>
<p>Да, именно отключить. SIP ALG переписывает заголовки и ломает NAT traversal. Пусть Kamailio разбирается с NAT сам.</p>
<h3>Проброс портов на Kamailio</h3>
<pre><code class="language-bash">
# 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"
</code></pre>
<h3>Схема: MikroTik + Kamailio</h3>
<pre class="mermaid">%%{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
</pre>
<h2>Безопасность SIP прокси</h2>
<p>SIP-серверы сканируются постоянно. На открытый порт 5060 начнут ломиться в первые же минуты после запуска. Это не паранойя — это реальность.</p>
<h3>Fail2ban против брутфорса</h3>
<pre><code class="language-bash">
nano /etc/fail2ban/filter.d/kamailio.conf
</code></pre>
<pre><code class="language-text">
[Definition]
failregex = kamailio.*authentication failure.*
kamailio.*407 Proxy Authentication Required.*
kamailio.*401 Unauthorized.*
ignoreregex =
</code></pre>
<pre><code class="language-bash">
nano /etc/fail2ban/jail.local
</code></pre>
<pre><code class="language-text">
[kamailio]
enabled = true
port = 5060,5061
protocol = udp
filter = kamailio
logpath = /var/log/syslog
maxretry = 5
bantime = 3600
findtime = 600
</code></pre>
<pre><code class="language-bash">
systemctl restart fail2ban
fail2ban-client status kamailio
</code></pre>
<h3>Pike — защита от SIP-флуда</h3>
<p>Fail2ban работает по логам с задержкой. Pike — модуль Kamailio, который режет флуд в реальном времени:</p>
<pre><code class="language-text">
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;
}
</code></pre>
<p>30 запросов за 2 секунды с одного IP — блокируем на 120 секунд. Для легитимных клиентов этого не заметно, для сканеров — стена.</p>
<h3>IP Whitelist для доверенных источников</h3>
<pre><code class="language-text">
# Только свои IP - остальным 403
if ($si != "192.168.1.0/24" && $si != "10.0.0.50") {
sl_send_reply("403", "Forbidden");
exit;
}
</code></pre>
<p>Если у тебя VoIP-провайдер с фиксированными IP — добавь их в whitelist. Все остальные пусть идут лесом.</p>
<h3>TLS для шифрования сигнализации</h3>
<pre><code class="language-bash">
# Самоподписанный сертификат (для продакшна используй Let's Encrypt)
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/kamailio/kamailio.key \
-out /etc/kamailio/kamailio.crt
</code></pre>
<pre><code class="language-bash">
nano /etc/kamailio/tls.cfg
</code></pre>
<pre><code class="language-text">
[server:default]
method = TLSv1.2+
verify_certificate = no
require_certificate = no
private_key = /etc/kamailio/kamailio.key
certificate = /etc/kamailio/kamailio.crt
</code></pre>
<pre><code class="language-text">
# В kamailio.cfg добавь:
loadmodule "tls.so"
modparam("tls", "config", "/etc/kamailio/tls.cfg")
listen=tls:0.0.0.0:5061
</code></pre>
<h2>Мониторинг SIP-прокси</h2>
<h3>sngrep — интерактивный SIP-монитор</h3>
<p>Это первый инструмент при любой проблеме. Показывает SIP-диалоги в реальном времени:</p>
<pre><code class="language-bash">
# Интерактивный режим
sngrep
# Фильтр по IP
sngrep host 192.168.1.100
# Только INVITE
sngrep -i "INVITE"
# Сохранить в PCAP для анализа в Wireshark
sngrep -O /tmp/sip-debug.pcap
</code></pre>
<p>В интерактивном режиме: стрелками выбирай диалог, Enter — подробности, F7 — фильтры.</p>
<h3>Prometheus exporter для Kamailio</h3>
<pre><code class="language-bash">
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
</code></pre>
<pre><code class="language-text">
[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
</code></pre>
<pre><code class="language-bash">
systemctl daemon-reload
systemctl enable --now kamailio_exporter
# Метрики: http://localhost:9494/metrics
</code></pre>
<h3>Логирование в JSON для Grafana/Loki</h3>
<pre><code class="language-text">
# В kamailio.cfg
xlog("L_INFO", "{\"ts\":\"$TV(Sn)\", \"method\":\"$rm\", \"from\":\"$fu\", \"to\":\"$ru\", \"src\":\"$si\"}\n");
</code></pre>
<p>Настрой Promtail для чтения <code>/var/log/syslog</code> и парсинга JSON — получишь полную картину трафика в Grafana.</p>
<h2>Устранение типовых проблем</h2>
<h3>Односторонняя слышимость</h3>
"Симптом:
<br />
Самая частая проблема в VoIP за NAT. Это не баг Kamailio — это отсутствие RTP-прокси. SIP-сигнализация прошла, а медиапоток упёрся в NAT и не дошёл.<br />
<p>Решение — поставить RTPengine:</p>
<pre><code class="language-bash">
apt install -y rtpengine
</code></pre>
<pre><code class="language-text">
# В 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();
}
}
</code></pre>
<h3>BYE и re-INVITE идут мимо прокси</h3>
<p>Причина — забытый <code>record_route()</code>. Проверь, что он стоит для INVITE и SUBSCRIBE:</p>
<pre><code class="language-text">
if (method=="INVITE" || method=="SUBSCRIBE") {
record_route();
}
</code></pre>
<p>И что <code>loose_route()</code> обрабатывается до основной логики:</p>
<pre><code class="language-text">
if (loose_route()) {
t_relay();
exit;
}
</code></pre>
<h3>Kamailio не слушает на нужном IP</h3>
<pre><code class="language-bash">
# Проверяем что слушает
netstat -tulnp | grep 5060
ss -tulnp | grep 5060
</code></pre>
<p>Если нужного IP нет — добавь в конфиг:</p>
<pre><code class="language-text">
listen=udp:192.168.1.50:5060
listen=udp:10.0.0.50:5060
listen=tcp:0.0.0.0:5060
</code></pre>
<h3>DNS не резолвится</h3>
<pre><code class="language-bash">
# Проверяем резолв
dig provider.com SRV
dig _sip._udp.provider.com SRV
cat /etc/resolv.conf
</code></pre>
<p>В kamailio.cfg включи <a class="wpil_keyword_link" title="DNS" href="https://it-apteka.com/tag/dns/" target="_blank" rel="noopener" data-wpil-keyword-link="linked" data-wpil-monitor-id="1707">DNS</a>:</p>
<pre><code class="language-text">
dns=yes
rev_dns=yes
</code></pre>
<h3>Ошибка «kamailio -c» при проверке конфига</h3>
<pre><code class="language-bash">
kamailio -c -f /etc/kamailio/kamailio.cfg 2>&1 | head -30
</code></pre>
<p>Читай вывод внимательно — там будет номер строки с ошибкой. Чаще всего: незакрытые скобки, опечатки в именах модулей, отсутствующий модуль.</p>
<p>Проверь, что все модули из <code>loadmodule</code> реально установлены:</p>
<pre><code class="language-bash">
dpkg -l | grep kamailio
ls /usr/lib/kamailio/modules/ | grep pike
</code></pre>
<h3>TLS не поднимается</h3>
<pre><code class="language-bash">
# Проверяем сертификат
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
# Хэши должны совпасть
</code></pre>
<h3>Flood от провайдера или сканеров</h3>
<pre><code class="language-bash">
# Смотрим кто атакует
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
</code></pre>
<p>Если атаки регулярные — поставь Pike (описан выше) и настрой Fail2ban.</p>
<h2>Резервное копирование</h2>
<p>Что бэкапить:</p>
<pre><code class="language-bash">
# Конфиги 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
</code></pre>
<p>Как восстановить:</p>
<pre><code class="language-bash">
# Восстановление конфига
tar xzf /backup/kamailio-config-20240101.tar.gz -C /
# Проверка синтаксиса после восстановления
kamailio -c -f /etc/kamailio/kamailio.cfg
# Рестарт
systemctl restart kamailio
</code></pre>
<h2>Обновление Kamailio</h2>
<pre><code class="language-bash">
# До обновления - бэкап
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
</code></pre>
<p>Если что-то сломалось после обновления — откатываемся:</p>
<pre><code class="language-bash">
# Восстанавливаем конфиг
tar xzf /backup/kamailio-before-update.tar.gz -C /
# Откатываем пакет (если нужно)
apt install kamailio=5.7.x-1
</code></pre>
<h2>Чек-лист перед запуском в продакшн</h2>
<ul>
<li><a href="https://it-apteka.com/zapusk-bash-skriptov-v-linux-cherez-terminal-cron-python-windows-i-raspberry-pi/" title="Запуск bash скрипта: chmod, cron, Python, Windows и Raspberry Pi" target="_blank" rel="noopener" data-wpil-monitor-id="2348">Debian 12 / Ubuntu</a> 22.04 обновлён до актуальных пакетов</li>
<li>sysctl оптимизации применены и сохранены</li>
<li>Kamailio / OpenSIPS версия актуальная (5.8+ / 3.4+)</li>
<li><code>kamailio -c</code> проходит без ошибок</li>
<li><code>record_route()</code> стоит для INVITE и SUBSCRIBE</li>
<li><code>loose_route()</code> обрабатывается в начале route</li>
<li>Файрвол настроен: 5060 UDP/TCP открыт, остальное закрыто</li>
<li>Fail2ban активен, jail для kamailio настроен</li>
<li>Pike модуль подключён для защиты от флуда</li>
<li>TLS сертификаты установлены (если нужен SIPS)</li>
<li>RTPengine поднят (если есть NAT-клиенты)</li>
<li><a title="Настройка SIP телефонии за MikroTik и отключение SIP ALG" href="https://it-apteka.com/nastrojka-sip-telefonii-za-mikrotik-i-otkljuchenie-sip-alg/" target="_blank" rel="noopener" data-wpil-monitor-id="1716">SIP ALG на MikroTik</a> отключён</li>
<li>sngrep установлен, тестовый звонок проверен в трейсе</li>
<li>BYE после звонка проходит через прокси (проверь в sngrep)</li>
<li>Логирование настроено, ротация логов работает</li>
<li>Бэкап конфига настроен по крону</li>
<li>Схема <a class="wpil_keyword_link" title="Сети" href="https://it-apteka.com/category/networks/" target="_blank" rel="noopener" data-wpil-keyword-link="linked" data-wpil-monitor-id="1713">сети</a> и конфиги задокументированы</li>
</ul>
<h2>FAQ</h2>
<h3>Почему Kamailio, а не просто Asterisk?</h3>
<p>Asterisk — B2BUA. Он разрывает каждый SIP-диалог на два независимых плеча. Это добавляет задержку, потребляет больше ресурсов и не масштабируется на высокие нагрузки. Kamailio работает как настоящий прокси — пересылает запросы без разрыва диалога. На одинаковом железе Kamailio обслуживает в 10 раз больше звонков. Для 50 абонентов разница несущественна. Для 5000 — принципиальна.</p>
<h3>Как проверить, что Record-Route работает правильно?</h3>
<p>Запусти <code>sngrep</code>, сделай тестовый звонок и посмотри на трейс. В INVITE должен быть заголовок <code>Record-Route</code> с IP твоего прокси. В последующем BYE должен быть заголовок <code>Route</code> с тем же адресом. Если BYE идёт напрямую между клиентами — record_route не работает.</p>
<pre><code class="language-bash">
# Быстрая проверка в логах
grep "BYE" /var/log/syslog | grep kamailio
# Если строки есть - BYE проходит через прокси
</code></pre>
<h3>Что если провайдер не принимает INVITE через прокси?</h3>
<p>Провайдер смотрит на From-header и Contact. Если там IP внутреннего клиента вместо IP прокси — он отвергает запрос. Решение — UAC Replace в Kamailio:</p>
<pre><code class="language-text">
loadmodule "uac.so"
# Заменяем From на наш внешний IP
uac_replace_from("", "sip:$fU@твой-внешний-IP");
</code></pre>
<h3>Почему SIP ALG на MikroTik надо отключать?</h3>
<p>SIP ALG пытается помочь с NAT: переписывает IP-адреса в SIP-заголовках. Но делает это неправильно в 90% случаев: ломает Via-заголовки, портит Contact, создаёт дубли пакетов. Если у тебя стоит нормальный SIP прокси с RTPengine — ALG только мешает. Отключай сразу.</p>
<h3>Как балансировать не по round-robin, а по нагрузке?</h3>
<p>В OpenSIPS dispatcher поддерживает несколько алгоритмов. Алгоритм <code>10</code> — балансировка по нагрузке на основе активных звонков. Нужен модуль <code>load_balancer</code> вместо dispatcher или совместное использование. Алгоритм <code>8</code> в dispatcher — weighted random, распределение по весам из базы.</p>
<h3>Как откатиться, если конфиг сломал всё?</h3>
<pre><code class="language-bash">
# Восстанавливаем бэкап конфига
cp /etc/kamailio/kamailio.cfg.orig /etc/kamailio/kamailio.cfg
# Проверяем синтаксис
kamailio -c -f /etc/kamailio/kamailio.cfg
# Перезапускаем
systemctl restart kamailio
</code></pre>
<p>Именно поэтому бэкап перед любым изменением — не опция, а обязательный шаг.</p>
<h2>Итог</h2>
<p>У тебя теперь есть всё для запуска SIP прокси в продакшне: понимание архитектуры, рабочие конфиги Kamailio и OpenSIPS, интеграция с MikroTik, защита от атак и решение типовых проблем.</p>
<p>Три главных вещи, которые реально важны:</p>
<p>Первое — <code>record_route()</code> обязателен. Без него ты не контролируешь диалог после INVITE. Второе — SIP ALG на MikroTik отключи сразу. Третье — если есть NAT-клиенты, RTPengine нужен с самого начала, не после того как пользователи начнут жаловаться.</p>
<p>Начни с простого stateless proxy, убедись что понимаешь трейс в sngrep, потом добавляй RTPengine и балансировку. Не пытайся сразу построить идеальную систему — сначала сделай работающую.</p>
"Не
<br />
Пиши в комментарии. Прикладывай вывод sngrep или фрагмент логов — разберём. Без этого диагностировать что-то по описанию "не работает" — занятие неблагодарное.<br />
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 или фрагмент логов — разберём. Без этого диагностировать что-то по описанию «не работает» — занятие неблагодарное.