El manual de referencia más completo sobre Kamailio en castellano. Documentación, tutoriales, módulos y guías de instalación para las versiones 5 y 6.
Kamailio es un servidor SIP de código abierto y alto rendimiento, heredero directo del proyecto OpenSER (que a su vez derivó de SER — SIP Express Router, creado en 2001 por Fraunhofer FOKUS). Es uno de los servidores SIP más utilizados en el mundo para construir infraestructuras de voz sobre IP (VoIP), plataformas de comunicaciones unificadas, WebRTC y redes de telecomunicaciones a escala operadora.
Kamailio actúa como proxy SIP, registrar, redirect server y location server. Su arquitectura modular y su potente lenguaje de scripting (kamailio.cfg) lo hacen idóneo tanto para instalaciones pequeñas como para despliegues masivos con millones de usuarios simultáneos.
Capaz de procesar decenas de miles de llamadas por segundo en hardware convencional. Arquitectura no bloqueante y multihilo (con TLS multihilo desde 6.1).
Más de 250 módulos disponibles: autenticación, bases de datos, NAT traversal, IMS, WebRTC, RTPEngine, LDAP, Redis, Kafka, NATS y mucho más.
Lenguaje de configuración nativo muy potente, más soporte KEMI para scripts en Python 3, Lua, JavaScript, Ruby y Go.
UDP, TCP, TLS, WebSocket (WSS), SCTP, IPv6. Compatible con WebRTC, IMS/LTE, SIP SIMPLE, presencia y SIPREC.
TLS/SRTP, autenticación SIP digest, anti-flood, listas negras, algoritmos de hash robustos (desde 6.1) y módulo secfilter.
Usado por operadoras de telecomunicaciones, proveedores VoIP y grandes plataformas de comunicaciones en todo el mundo.
| Año | Hito |
|---|---|
| 2001 | SER (SIP Express Router) creado por Fraunhofer FOKUS — primer servidor SIP open source de alto rendimiento |
| 2002 | SER liberado como open source bajo GPLv2 |
| 2005 | Fork de SER: nace OpenSER con una comunidad más abierta |
| 2008 | OpenSER se renombra a Kamailio por reclamaciones de marca |
| 2012 | Fusión con el proyecto SER: Kamailio absorbe el código base de SER |
| 2016 | Kamailio 5.0 — gran refactorización y soporte KEMI (Python, Lua, JavaScript, Ruby) |
| 2025 | Kamailio 6.0 — nueva arquitectura de módulos, mejoras KEMI, soporte QUIC experimental |
| Feb 2026 | Kamailio 6.1.0 — TLS multihilo, SIPREC con RTPEngine, hashing más robusto, 4 módulos nuevos |
| May 2026 | Kamailio 6.1.3 — última versión estable disponible |
Kamailio sigue un ciclo de versiones semestral. A continuación las ramas activas y las últimas de la serie 5.x:
| Versión | Publicación | Estado | Novedades principales | Descarga |
|---|---|---|---|---|
| 6.1.3 | Mayo 2026 | Activa | Correcciones de estabilidad sobre 6.1.x. Última versión recomendada para nuevas instalaciones. | Descargar ↗ |
| 6.1.0 | Feb 2026 | Activa | TLS multihilo, SIPREC con RTPEngine, hashing robusto (SHA-256/512), 4 nuevos módulos: dlgs, siprepo, outbound_dmq, stir_shaken mejorado | Descargar ↗ |
| 6.0.x | 2025 | Mantenimiento | Nueva API de módulos, mejoras KEMI, soporte QUIC experimental, refactorización del core | Descargar ↗ |
| 5.8.x | 2024 | LTS | Mejoras en RTPEngine, módulo lost (location services), mejoras en dispatcher, correcciones de seguridad continuadas | Descargar ↗ |
| 5.7.x | 2023 | EOL | Nuevo módulo nats (NATS.io), mejoras en http_async_client, soporte Go KEMI | Descargar ↗ |
| 5.6.x | 2022 | EOL | Módulo mqtt, mejoras WebSocket, jsonrpcs mejorado, soporte SIP over QUIC experimental | Descargar ↗ |
| 5.5.x | 2021 | EOL | Módulo cfgt, mejoras de rendimiento en el core, módulo topos_redis | Descargar ↗ |
Kamailio carga funcionalidad a través de módulos (.so). Se cargan con loadmodule "nombre.so" y se configuran con modparam().
calculate_ha1loadmodule "auth.so"
loadmodule "auth_db.so"
loadmodule "db_mysql.so"
modparam("auth_db", "db_url", "mysql://kamailio:pass@localhost/kamailio")
modparam("auth_db", "calculate_ha1", yes) # la BD guarda password en texto plano
modparam("auth_db", "password_column", "password")
modparam("auth_db", "user_column", "username")
modparam("auth_db", "domain_column", "domain")
# En request_route:
if (!auth_check("$fd", "subscriber", "1")) {
auth_challenge("$fd", "0");
exit;
}
loadmodule "sqlops.so"
modparam("sqlops","sqlcon","ca=>mysql://kamailio:pass@localhost/kamailio")
# En request_route:
sql_query("ca", "SELECT did FROM did_routing WHERE number='$rU'", "res");
if($dbr(res=>rows) > 0) {
$ru = "sip:" + $dbr(res=>[0,0]) + "@gateway.local";
}
sql_result_free("res");
loadmodule "dispatcher.so"
modparam("dispatcher", "db_url", "mysql://kamailio:pass@localhost/kamailio")
modparam("dispatcher", "ds_ping_interval", 10) # ping cada 10s para detectar caídas
modparam("dispatcher", "ds_probing_mode", 1) # probar todos los destinos
# En request_route:
if (is_method("INVITE")) {
if (!ds_select_dst("1", "4")) { # grupo 1, algoritmo round-robin
send_reply(503, "Service Unavailable");
exit;
}
}
# Gestionar fallos (event_route o failure_route):
failure_route[MANAGE_FAILURE] {
if (t_is_canceled()) exit;
if (t_check_status("500|503")) {
if (ds_next_dst()) {
t_relay();
exit;
}
}
}
loadmodule "nathelper.so"
loadmodule "rtpengine.so"
modparam("nathelper", "natping_interval", 30)
modparam("nathelper", "ping_nated_only", 1)
modparam("rtpengine", "rtpengine_sock", "udp:127.0.0.1:2223")
route[MEDIA] {
if (is_method("INVITE") || is_method("UPDATE")) {
if (nat_uac_test(19)) {
fix_nated_contact();
rtpengine_offer("replace-origin replace-session-connection");
}
}
}
onreply_route[REPLY_MEDIA] {
if (nat_uac_test(19)) {
rtpengine_answer("replace-origin replace-session-connection");
fix_nated_contact();
}
}
# kamailio.cfg — activar KEMI Python
loadmodule "app_python3.so"
modparam("app_python3", "load", "/etc/kamailio/kamailio_route.py")
cfgengine "python"
# /etc/kamailio/kamailio_route.py
import kamailio
def ksr_request_route():
KSR.info("Petición: {} desde {}\n".format(
KSR.pv.get("$rm"), KSR.pv.get("$si")))
if KSR.is_REGISTER():
return ksr_route_registrar()
if KSR.siputils.has_totag() > 0:
if KSR.rr.loose_route() > 0:
return ksr_route_relay()
def ksr_route_registrar():
if KSR.registrar.save("location", 0) < 0:
KSR.sl.sl_reply_error()
return
def ksr_route_relay():
if KSR.tm.t_relay() < 0:
KSR.sl.sl_reply_error()
return
loadmodule "pike.so"
loadmodule "htable.so"
modparam("pike", "sampling_time_unit", 2)
modparam("pike", "reqs_density_per_unit", 30) # max 30 req/2s por IP
modparam("pike", "remove_latency", 4)
modparam("htable", "htable", "ipban=>size=8;autoexpire=300")
request_route {
# Bloquear IPs baneadas
if ($sht(ipban=>$si) != $null) {
xlog("L_WARN", "IP baneada: $si\n");
exit;
}
# Detectar flood
if (!pike_check_req()) {
$sht(ipban=>$si) = 1;
xlog("L_WARN", "Flood detectado, baneando $si por 300s\n");
exit;
}
}
# 1. Añadir clave GPG y repositorio oficial
curl -fsSL https://deb.kamailio.org/kamailiodebkey.gpg | sudo gpg --dearmor \
-o /usr/share/keyrings/kamailio.gpg
# Debian 12 (Bookworm) / Ubuntu 24.04:
echo "deb [signed-by=/usr/share/keyrings/kamailio.gpg] \
https://deb.kamailio.org/kamailio61 bookworm main" \
| sudo tee /etc/apt/sources.list.d/kamailio.list
# 2. Instalar paquetes base + módulos más comunes
sudo apt update
sudo apt install kamailio kamailio-mysql-modules kamailio-tls-modules \
kamailio-websocket-modules kamailio-utils-modules kamailio-extras-modules
# 3. Crear base de datos
kamdbctl create
# 4. Habilitar e iniciar
sudo systemctl enable kamailio
sudo systemctl start kamailio
sudo systemctl status kamailio
sudo dnf install epel-release
sudo curl -fsSL https://rpm.kamailio.org/kamailio61/kamailio.repo \
-o /etc/yum.repos.d/kamailio.repo
sudo dnf install kamailio kamailio-mysql kamailio-tls kamailio-websocket
kamdbctl create
sudo systemctl enable --now kamailio
docker pull kamailio/kamailio:6.1-debian
docker run -d \
--name kamailio \
--network host \
-v /etc/kamailio:/etc/kamailio \
kamailio/kamailio:6.1-debian
# Dependencias (Debian/Ubuntu)
sudo apt install -y git gcc flex bison make libmysqlclient-dev \
libssl-dev libpcre3-dev libcurl4-openssl-dev libxml2-dev libevent-dev
# Clonar y compilar versión 6.1
git clone --depth 1 --branch 6.1 https://github.com/kamailio/kamailio.git
cd kamailio
make FLAVOUR=kamailio include_modules="db_mysql tls websocket nathelper \
rtpengine dispatcher app_python3" cfg
make all
sudo make install
| Distribución | Versiones soportadas | Repositorio |
|---|---|---|
| Debian 12 (Bookworm) | 5.8, 6.0, 6.1 | deb.kamailio.org |
| Debian 11 (Bullseye) | 5.8, 6.0 | deb.kamailio.org |
| Ubuntu 24.04 LTS | 5.8, 6.0, 6.1 | deb.kamailio.org |
| Ubuntu 22.04 LTS | 5.7, 5.8, 6.0 | deb.kamailio.org |
| AlmaLinux / Rocky 9 | 5.8, 6.0, 6.1 | rpm.kamailio.org |
| Docker (todas) | 5.6–6.1 | hub.docker.com |
El fichero principal es /etc/kamailio/kamailio.cfg. Se organiza en cuatro bloques: directivas globales, carga de módulos, parámetros de módulos y bloques de rutas.
#!KAMAILIO
#!define DBURL "mysql://kamailio:pass@localhost/kamailio"
# ── Parámetros globales ──────────────────────────────────────────────
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
listen=tls:0.0.0.0:5061
# ── Módulos ──────────────────────────────────────────────────────────
loadmodule "tm.so"
loadmodule "sl.so"
loadmodule "rr.so"
loadmodule "usrloc.so"
loadmodule "registrar.so"
loadmodule "auth.so"
loadmodule "auth_db.so"
loadmodule "db_mysql.so"
loadmodule "nathelper.so"
loadmodule "xlog.so"
loadmodule "maxfwd.so"
loadmodule "textops.so"
# ── Parámetros de módulos ────────────────────────────────────────────
modparam("usrloc", "db_url", DBURL)
modparam("usrloc", "db_mode", 2) # write-back caché + BD
modparam("auth_db", "db_url", DBURL)
modparam("auth_db", "calculate_ha1", yes)
modparam("auth_db", "password_column", "password")
modparam("rr", "enable_full_lr", 1)
# ── Rutas ────────────────────────────────────────────────────────────
request_route {
xlog("L_INFO", "[$ci] $rm $ru desde $fu ($si:$sp)\n");
if (!mf_process_maxfwd_header(10)) {
sl_send_reply(483, "Too Many Hops"); exit;
}
if (is_method("REGISTER")) {
route(AUTH);
route(REGISTRAR);
exit;
}
if (is_method("INVITE|SUBSCRIBE")) { record_route(); }
if (has_totag()) {
if (loose_route()) { route(RELAY); }
exit;
}
if (is_method("INVITE")) {
route(AUTH);
route(LOCATION);
}
}
route[AUTH] {
if (!auth_check("$fd", "subscriber", "1")) {
auth_challenge("$fd", "0");
exit;
}
consume_credentials();
}
route[REGISTRAR] {
if (!save("location")) { sl_reply_error(); }
exit;
}
route[LOCATION] {
if (!lookup("location")) {
$var(rc) = $retcode;
if ($var(rc) == -1 || $var(rc) == -3) {
send_reply(404, "Not Found"); exit;
}
send_reply(405, "Method Not Allowed"); exit;
}
route(RELAY);
}
route[RELAY] {
if (!t_relay()) { sl_reply_error(); }
exit;
}
loadmodule "tls.so"
modparam("tls", "config", "/etc/kamailio/tls.cfg")
modparam("tls", "tls_threads_mode", 1) # multihilo — novedad 6.1
# /etc/kamailio/tls.cfg
[server:default]
method = TLSv1.2+
verify_certificate = no
require_certificate = no
private_key = /etc/ssl/kamailio/privkey.pem
certificate = /etc/ssl/kamailio/fullchain.pem
loadmodule "xhttp.so"
loadmodule "websocket.so"
loadmodule "nathelper.so"
loadmodule "rtpengine.so"
modparam("websocket", "keepalive_mechanism", 1)
modparam("websocket", "keepalive_interval", 30)
modparam("rtpengine", "rtpengine_sock", "udp:127.0.0.1:2223")
listen=tcp:0.0.0.0:8080 # WS
listen=tls:0.0.0.0:4443 # WSS
event_route[xhttp:request] {
set_reply_close();
set_reply_no_connect();
if (ws_handle_handshake()) exit;
send_reply(404, "Not found");
}
event_route[websocket:closed] {
xlog("L_INFO", "WS cerrado $si:$sp\n");
}
# Estado del servidor
kamctl status
# Ver registraciones activas
kamctl ul show
kamctl ul show usuario@dominio.com
# Recargar dispatcher desde BD (sin reiniciar)
kamcmd dispatcher.reload
# Estadísticas en tiempo real
kamcmd stats.get_statistics all
kamcmd stats.get_statistics "inuse_transactions:"
# Número de llamadas activas
kamcmd tm.stats
# Ver conexiones TLS activas
kamcmd tls.info
# Banear una IP manualmente
kamcmd htable.seti ipban 192.168.1.100 1
# Enviar SIP OPTION de prueba
kamctl fifo via_list
Las pseudovariables permiten acceder a campos del mensaje SIP y del entorno de ejecución directamente desde el script. Su sintaxis es $nombre o $(nombre{transformacion}).
| Variable | Descripción | Ejemplo |
|---|---|---|
| $rm | Método SIP | INVITE, REGISTER, BYE… |
| $ru | Request URI completo | sip:alice@ejemplo.com |
| $rU | Parte usuario del Request URI | alice |
| $rd | Dominio del Request URI | ejemplo.com |
| $rp | Puerto del Request URI | 5060 |
| $fu | From URI completo | sip:bob@dominio.com |
| $fU | Usuario del From | bob |
| $fd | Dominio del From | dominio.com |
| $fn | Display name del From | Bob Smith |
| $tu | To URI completo | sip:alice@ejemplo.com |
| $tU | Usuario del To | alice |
| $ci | Call-ID | abc123@192.168.1.1 |
| $cs | CSeq número | 1 |
| $ct | Contact header URI | sip:bob@192.168.1.10:5080 |
| $ml | Message length (bytes) | 512 |
| Variable | Descripción |
|---|---|
| $rs | Reply Status code (200, 404, 500…) |
| $rr | Reply Reason phrase (OK, Not Found…) |
| Variable | Descripción |
|---|---|
| $si | IP fuente del paquete SIP |
| $sp | Puerto fuente |
| $Ri | IP de la interfaz receptora de Kamailio |
| $Rp | Puerto de la interfaz receptora |
| $proto | Protocolo (udp, tcp, tls, ws, wss) |
| $af | Familia de dirección (INET o INET6) |
# AVP — por transacción, tipadas (int o string)
$avp(nombre) = "valor string";
$avp(i:42) = 100;
# $var — por proceso/petición, alta velocidad
$var(contador) = $var(contador) + 1;
# $dlg_var — persiste durante todo el diálogo (requiere módulo dialog)
$dlg_var(clave) = "valor permanente del diálogo";
# $sht — hash table compartida entre todos los procesos (requiere htable)
$sht(tabla=>clave) = "compartido";
if ($sht(ipban=>$si) != $null) { exit; }
# Cabeceras SIP
xlog("Contact: $hdr(Contact)\n");
xlog("2º Via: $(hdr(Via)[1])\n"); # índice base 0
# Transformaciones
xlog("Usuario en mayúsculas: $(rU{s.upper})\n");
xlog("IP válida: $(si{ip.isavp})\n");
xlog("Longitud de rU: $(rU{s.len})\n");
$var(host) = $(ru{uri.host}); # extraer host del URI