Kamailio : tutoriel découverte partie 1

J’ai découvert Kamailio il y a un an alors que mon besoin était de développer un SBC (Session Border Controller) qui avait pour fonction principale de protéger une instance Asterisk. Entre temps, le besoin initial a évolué et par définition la solution technique également. J’ai pu monter en compétence sur le logiciel et par la même occasion acquis de la souplesse avec celui-ci dans une stack technique VoIP.

Alors que les ressources en ligne concernant les cas d’usage de Kamailio s’avèrent relativement limitées, je vais essayer d’expliquer ce logiciel au travers d’une série d’articles avec des exemples de configuration.

En premier lieu et avant de engouffrer plus largement dans cet tutoriel, il est recommandé d’avoir des connaissances en SIP (RFC 3261).

Définitions

Pour mieux comprendre les concepts mentionnés dans cet article et l’écosystème Kamailio en général, voici une liste des définitions essentielles.

Rôles SIP fondamentaux

  • SIP (Session Initiation Protocol) : Un protocole de signalisation de la couche application utilisé pour initier, maintenir et terminer des sessions en temps réel incluant de la voix, de la vidéo et de la messagerie.
  • UAC (User Agent Client) : Une entité logique qui crée une nouvelle requête SIP. Par exemple, lorsque vous décrochez un téléphone VoIP pour composer un numéro, le téléphone agit comme un UAC pour initier la requête INVITE.
  • UAS (User Agent Server) : Une entité logique qui génère une réponse à une requête SIP. Lorsqu’un téléphone reçoit un INVITE et renvoie un 180 Ringing ou un 200 OK, il agit en tant qu’UAS.
  • B2BUA (Back-to-Back User Agent) : Contrairement à un proxy, un B2BUA agit simultanément comme un UAS et un UAC. Il termine le segment d’appel (call leg) entrant et en initie un nouveau sortant, ce qui lui donne un contrôle complet sur les médias et la signalisation (ex. : Asterisk ou FreeSWITCH).

Remarque : La plupart des points de terminaison SIP (comme les téléphones IP ou les PBX) agissent à la fois comme UAC et UAS, selon qu’ils émettent ou reçoivent un appel.

Composants VoIP

  • Proxy SIP : Un serveur qui agit comme un intermédiaire, relayant les requêtes SIP vers une autre entité. La force principale de Kamailio est d’agir comme un proxy programmable à haute performance.
  • Registrar : Un serveur qui accepte les requêtes REGISTER et stocke les informations reçues (l’association entre l’URI d’un utilisateur et son adresse IP actuelle) dans un service de localisation (location service).
  • SBC (Session Border Controller) : Un équipement spécialisé ou un logiciel (comme Kamailio) utilisé pour protéger et gérer les flux de signalisation et de médias à la « bordure » d’un réseau. Il gère la sécurité (masquage de la topologie interne), la traversée de NAT et la normalisation des protocoles.
  • AoR (Address of Record) : Une URI SIP qui pointe vers un domaine disposant d’un service de localisation où l’utilisateur peut être joint. Par exemple : sip:user@example.com.
  • RTPEngine : Un proxy pour le trafic RTP. Étant donné que Kamailio ne gère généralement que la signalisation (SIP), il utilise souvent RTPEngine pour relayer les données audio/vidéo réelles (RTP) entre différentes interfaces réseau et différents utilisateurs.

Qu’est-ce que Kamailio ?

Kamailio (anciennement OpenSER) est un serveur SIP gratuit et open source. Il est écrit en C avec une attention toute particulière pour la performance. Kamailio est hautement configurable et peut agir comme registrar, proxy ou encore load-balancer SIP, grâce à son architecture modulaire.

Contrairement à ce que l’on pourrait penser, Kamailio n’est pas un PBX et diffère d’Asterisk, FreeSwitch et consorts. Kamailio n’est pas non plus un B2BUA (Back-to-Back User Agent) et ne gère que la signalisation (SIP) là où un PBX va en plus gérer les médias (voix) ou encore avoir des fonctions de call-center.

Pour répondre à un besoin avec Kamailio vous devez le configurer. La configuration initiale de Kamailio ne fait rien, cependant elle donne un aperçu des possibilités du logiciel. C’est aussi en ce sens qu’il est nécessaire d’avoir des connaissances en SIP, car vous devez avoir une idée des requêtes et réponses nécessaires au bon fonctionnement de ce logiciel.

Note : Kamailio ne gère pas les médias. Pour cela je vous invite à utiliser RTPEngine de SIPWise.

Où trouver la documentation Kamailio ?

Sur le site officiel de Kamailio vous pouvez retrouver deux documentations : le wiki officiel et celle des modules. La documentation officielle est très complète et aussi bien le Wiki, que les pages des modules, éclairent très bien la configuration de Kamailio.

En revanche, lorsqu’il s’agit des cas d’usage et des architectures avec des composants tiers, il est plus difficile d’avoir un aperçu de haut niveau. Des personnages comme Fred POSNER font souvent les éloges de Kamailio et de grâce, il existe la chaîne YouTube Kamailio World. En somme, il est aussi possible de s’inspirer de la documentation OpenSIPS et de ses tutoriels, cependant on y trouve très vite de divergences.

Installer Kamailio

Kamailio est disponible sur Linux et BSD. Sur Ubuntu, installez Kamailio depuis les dépôts officiel : $ sudo apt install kamailio

Éditez la configuration : /etc/kamailio.cfg .

Il est aussi possible d’utiliser Kamailio avec Docker avec une configuration comme ci-après :

networks:
  default:
  # database:
  #   external: true

services:
  # Primary Kamailio instance
  kamailio:
    image: ghcr.io/kamailio/kamailio:6.0.4-bookworm
    restart: unless-stopped
    volumes:
      - ./kamailio:/etc/kamailio
      - ./kamailio/logs/kamailio:/var/log/kamailio
    network_mode: host # Expose 5060 for TCP/UDP and 5061 for TLS

  # RTP Engine service
  rtpengine:
    image: fonoster/rtpengine:latest
    container_name: rtpengine
    restart: unless-stopped
    network_mode: "host" # At the moment this option only works in Linux
    environment:
      # RTPENGINE_PUBLIC_IP: ${DOCKER_HOST_ADDRESS:-192.168.1.210} When commented, use Netdiscover (https://github.com/fonoster/rtpengine/blob/main/Dockerfile)
      RTPENGINE_BIND_NG_IP: ${RTPENGINE_BIND_NG_IP:-127.0.0.1}
      RTPENGINE_BIND_NG_PORT: ${RTPENGINE_BIND_NG_PORT:-2223}
      RTPENGINE_PORT_MIN: 10000
      RTPENGINE_PORT_MAX: 20000
      RTPENGINE_LOG_LEVEL: "6"

Notez tout de même que network_mode=host n’est supporté que sur Linux. Aussi, les protocoles SIP et RTP apprécient moyennement d’être confrontés à du NAT (Network Address Translation) si vous décidez d’exposer les ports de Kamailio et RTPEngine avec Docker.

Quelques notions de SIP

Pour ce premier article je vais lister lister quelque-unes des requêtes SIP à connaître. Ils vous seront utiles aussi bien pour travailler avec Kamailio que pour n’importe quel autre PBX.

Requête SIPDescription
INVITEInitie une session d’appel.
ACKConfirme la réception d’une réponse finale (ex. après INVITE).
BYETermine une session existante.
CANCELAnnule une requête INVITE en attente avant qu’elle ne soit répondue.
REGISTEREnregistre la localisation d’un utilisateur auprès d’un serveur SIP.
OPTIONSInterroge les capacités d’un serveur ou d’un point d’extrémité.
INFOTransporte des informations de contrôle en cours de session (ex. DTMF).
PRACKAccuse réception des réponses provisoires fiables lorsqu’elles sont utilisées.
UPDATEModifie les paramètres de la session sans refaire un INVITE.
REFERDemande au destinataire d’initier une nouvelle requête (souvent pour le transfert d’appel).

Découvrir Kamailio

C’est parti pour démarrer ce tutoriel avec Kamailio. Voici quelques notions de SIP qui vous seront utiles si vous êtes débutant. À défaut cela fera tout de même un rappel.

Exemple de requête INVITE

Prenons l’exemple d’une requête SIP qui permet de passer un appel : INVITE. Imaginons comme deux utilisateurs 1001 et 1002 et que 1001 souhaite appeler 1002.

Selon la RFC 3261, 1001 doit émettre une requête SIP à destination de 1002, cependant cela implique de savoir l’adresse IP et le port sur lequel 1002 est disponible. Dans la pratique, cela ne se passe jamais comme ça et 1001 va émettre cette requete à un serveur SIP qui se chargera de la relayer (à la façon d’un proxy) ou d’en émettre une nouvelle à la façon d’un PBX (B2BUA).

INVITE sip:1002@voip.operateur.re SIP/2.0

Dans un schéma avec deux téléphones, cette requête fait « sonner » le téléphone de 1002. Si nous envoyions ce message à un PBX générique, celui-ci aurait la logique nécessaire pour savoir qu’il dispose d’une extension 1001 et ferait sonner l’extension 1002.

Avec un PBX

Un PBX générique examine l’URI de requête dans le message INVITE qu’il a reçu et dispose d’une logique prédéfinie pour savoir que 1002 est un appareil qu’il a enregistré et que nous voulons nous connecter à cet appareil. Il envoie donc l’appel à l’appareil correspondant (1002). Ceci est le fonctionnement « classique » d’Asterisk, de FreeSwitch ou de n’importe quel PBX. Pour en dire plus à ce sujet, si nous envoyons cette requête à Asterisk, celui-ci vérifierai qu’il dispose des utilisateurs (endpoint dans PJSIP) et si le dialplan le permet redirigerai la requête vers le destinataire (exemple de ligne de dialplan : Dial(PJSIP/{EXTEN},30,tTr)). La gestion des réponses est automatique avec un PBX et celui se concentre sur la logique coeur, c’est à dire établir des appels entre les utilisateurs, qu’ils soient locaux ou distants par le biais d’un trunk par exemple.

Avec Kamailio

Kamailio fonctionne d’une toute autre façon. Si vous souhaitez que Kamailio réagisse à cette requête il faut l’écrire dans sa configuration et lui indiquer – à la façon d’un langage de programmation – les actions à prendre. Sommairement cela reviendrait à programmer Kamailio pour accepter les requêtes INVITE, vérifier si l’adresse d’enregistrement du destinataire (AoR : Address of Record) se trouve en mémoire, de répondre par un 100 Trying puis de transférer l’INVITE à la destination puis de répondre à l’appelant 200 OK, ce qui donne le diagramme suivant :

Flux d’appel utilisant Kamailio

Ici, j’ai omis le fait que nous devons également gérer les réponses 4XX si l’appelé est occupé ou absent, les utilisateurs ou encore les médias voix (RTP). Bien que tout cela semble difficile à gérer, il ne s’agit ici que de « programmation » au sens large du terme.

Même si cet exemple peut paraitre bateau, il vous permet de comprendre comment le système gère et achemine vos messages SIP. En somme, cela ouvre la porte à beaucoup de fonctionnalités, comme le fait de pouvoir gérer des autorisations d’appels pré-payé ou affranchi (post-paid), de sauvegarder le détail des communications (Call Detail Records), de faire du firewalling, du load-balancing, du LCR (Least Cost Routing), etc.

Le mot de la fin

Kamailio est un logiciel difficile à prendre en main. Les premières approches que vous aurez peuvent rebuter et vous aurez parfois l’envie d’abandonner. Avec un peu d’expérience il est possible de faire beaucoup de choses avec Kamailio qui peut être utilisé comme softswitch de classe 5 (pour entreprise) ou de classe 4 (pour opérateur).

Comment connecter deux instances Asterisk en trunk avec PJSIP

Dans le monde de la voix sur IP (VoIP), interconnecter des sites, bureaux, filiales ou encore des

Dans le monde de la communication VoIP, l’interconnexion de serveurs Asterisk est un vrai game-changer pour les petits FAI et les entreprises qui ont plusieurs bureaux et souhaitent avoir un système de téléphonie évolutif.

Que vous fournissiez des trunks SIP à vos clients ou que vous souhaitiez relier des bureaux annexes de manière fluide, ce guide vous explique comment configurer Asterisk avec PJSIP et le plan de numérotation (dialplan) à mettre en œuvre pour créer des interconnexions fiables.

Nous couvrirons les bases, la configuration pratique, le trunking VoIP et la gestion des endpoints SIP (utilisateurs).

Présentation d’Asterisk

Asterisk est le logiciel open-source pour la construction d’applications de communication. Il offre une multitude de fonctionnalités. Du simple soft switch de téléphonie à une gestion complexe des médias dans un SBC, Asterisk est très puissant.

Développé par Digium (désormais partie de Sangoma), il propulse des entreprises avec des PBX simples mais aussi centres d’appels plus complexes.

En somme, Asterisk gère les appels vocaux, la vidéo et les messages sur IP, ce qui le rend idéal comme plateforme de communication unifiée.

Asterisk a de nombreux avantages. En premier lieu, il est gratuit, hautement personnalisable et il prend en charge des protocoles comme SIP (avec le pilote PJSIP), XMPP ou encore SMTP (pour l’envoi de mails).

Dans un scénario de petit FAI, Asterisk vous permet d’agir comme un hub central, acheminant les appels entre les endpoints (clients) mais aussi vers les lignes de téléphonie classique (PSTN).

Comprendre les trunks

En téléphonie, un trunk désigne un chemin de communication capable de gérer plusieurs appels simultanés – comme une autoroute pour les appels téléphoniques.

Historiquement, les trunks étaient des lignes physiques bien spécifiques (en E1 en Europe ou T1 aux États-Unis), gérées par des géants des télécoms tels que France Télécom ou encore AT&T. Ces lignes pouvaient transporter des dizaines de canaux, formant le cœur des réseaux traditionnels de téléphonie fixe.

Avec l’essor d’internet, la VoIP les trunks ont évolués vers des connexions virtuelles utilisant des protocoles IP, permettant la démocratisation en entreprise de ce genre de liaisons.

Dans la configuration de trunk Asterisk, un trunk est essentiellement un lien logique entre votre serveur et un autre endpoint qui peut être un opérateur ou un PBX distant.

Avantages clés pour le trunking VoIP :

  • Économies de coûts : Pas besoin de matériel coûteux ; juste un accès à Internet.
  • Scalabilité : Gérer 10 ou 10 000 appels en ajoutant des ressources serveur. Parfait pour les centres d’appels.
  • Flexibilité : Acheminer les appels selon des règles, comme l’heure ou l’ID de l’appelant.

Qu’est-ce que SIP ? Le protocole qui alimente la VoIP moderne

SIP, ou Session Initiation Protocol, est la norme (RFC 3261) pour initier, maintenir et terminer des sessions en temps réel en VoIP. SIP gère la signalisation — pensez aux invitations, acceptations des appels ou encore clôture.

Remarque : les données vocales, la voix en tant que telle est gérée par un autre protocole.

Qu’est-ce que le média ? Gérer l’audio dans vos appels

Comme expliqué précédemment, SIP est un protocole de signalisation et ne gère pas les médias (voix, vidéo, etc.). Asterisk peut gérer les médias en concordance avec SIP. Alors que SIP gère le « qui » et le « quand » d’un appel, le média est le contenu réel — les flux voix, vidéo, le son, etc. En VoIP, les médias voyagent via RTP (Real-time Transport Protocol) sur UDP, séparément de la signalisation SIP. Des codecs comme G.711 ou Opus compressent et transmettent ces données.

Dans la gestion des médias Asterisk, vous pouvez choisir les codecs autorisés.

Configurer un trunk dans Asterisk pour les interconnexions

Nous configurerons deux serveurs Asterisk : Serveur A (votre hub principal FAI, agissant comme endpoint distant) et Serveur B (PBX client ou bureau annexe).

Ce tutoriel de trunk PJSIP suppose Asterisk 16+ avec PJSIP activé (vérifiez via module show like pjsip en CLI).

Prérequis pour une configuration réussie

  • Les deux serveurs sur des réseaux stables avec IP publiques ou STUN/TURN pour NAT.
  • Ports pare-feu ouverts : 5060 UDP/TCP (SIP), 10000-20000 UDP (médias RTP).
  • Installer Asterisk : dnf install asterisk (CentOS) ou sudo apt install asterisk (Ubuntu).
  • Sauvegarder les configs : cp /etc/asterisk/pjsip.conf /etc/asterisk/pjsip.conf.bak.

Recharger après modifications : asterisk -rx "pjsip reload".

Serveur A : Configuration de l’endpoint distant (côté FAI)

Sur le Serveur A (ex. IP : 192.0.2.1), créez un trunk pour accepter les connexions du Serveur B. Éditez /etc/asterisk/pjsip.conf :

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

[trunk-customer-b]
type=endpoint
transport=transport-udp
context=from-trunk  ; Dialplan context for incoming calls
disallow=all
allow=ulaw,alaw,gsm  ; Supported codecs for VoIP quality
auth=trunk-customer-b-auth
aors=trunk-customer-bdirect_media=no  ; Force media through server for recording/security

[trunk-customer-b-auth]
type=auth
auth_type=userpass
username=trunkuser  ; Shared secret with Server B
password=strongpass123
realm=192.0.2.1

[trunk-customer-b-aor]
type=aorcontact=sip:192.0.2.2:5060  ; Server B's IP

Cela configure le Serveur A comme un fournisseur de trunk SIP sécurisé. La section auth impose un nom d’utilisateur/mot de passe pour l’authentification PJSIP dans Asterisk, empêchant l’accès non autorisé.

Ajoutez maintenant des règles de plan de numérotation dans /etc/asterisk/extensions.conf pour acheminer les appels du trunk :

[from-trunk]
exten => _X.,1,NoOp(Incoming from trunk) 
same => n,Dial(PJSIP/${EXTEN}@local-extension)  ; Route to internal users same => n,Hangup()

Cela gère les appels entrants, les redirigeant vers les extensions locales. Pour les appels sortants vers le Serveur B, nous le verrons dans la section suivante.

Serveur B : Configuration de l’endpoint client (côté bureau annexe)

Sur le Serveur B (ex. IP : 192.0.2.2), enregistrez-vous auprès du Serveur A comme client trunk. Dans /etc/asterisk/pjsip.conf :

[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0:5060
local_net=192.168.0.0/16  ; Your internal network for NAT

[trunk-isp-a]
type=endpoint
transport=transport-udp
context=from-isp  ; Context for calls from Server A
disallow=all
allow=ulaw,alaw,gsm
auth=trunk-isp-a-auth
aors=trunk-isp-a-aor
outbound_auth=trunk-isp-a-auth
from_user=trunkuser
from_domain=192.0.2.1

[trunk-isp-a-auth]
type=auth
auth_type=userpass
username=trunkuser
password=strongpass123realm=192.0.2.1

[trunk-isp-a-aor]
type=aor
contact=sip:192.0.2.1:5060

Ici, le Serveur B s’authentifie auprès du Serveur A, activant un trunking VoIP bidirectionnel. Pour les appels sortants vers le trunk FAI :

Dans /etc/asterisk/extensions.conf :

[from-internal]
exten => _9NXXNXXXXXX,1,NoOp(Outbound to ISP) 
same => n,Set(CALLERID(num)=${CALLERID(num)})  ; Preserve caller ID 
same => n,Dial(PJSIP/${EXTEN:1}@trunk-isp-a)  ; Strip 9 prefix, dial via trunk 
same => n,Hangup()

[from-isp] 
exten => _X.,1,NoOp(Incoming from ISP trunk) 
same => n,Dial(Local/${EXTEN}@internal-extensions)  ; Route to local users same => n,Hangup()

Testez la configuration : Depuis le Serveur B, appelez une extension sur le Serveur A (ex. Dial(PJSIP/100@trunk-isp-a)). Utilisez pjsip show endpoints en CLI Asterisk pour vérifier l’enregistrement.

Dépannage des problèmes courants dans les interconnexions Asterisk PJSIP

  • Audio unidirectionnel : Activez direct_media=yes ou vérifiez les ports RTP/pare-feu.
  • Échec d’enregistrement : Vérifiez que les identifiants d’authentification et les realms correspondent.
  • Incompatibilité de codecs : Alignez allow/disallow des deux côtés.

Pour un dépannage avancé d’Asterisk, activez les logs de débogage : pjsip set logger on.

Meilleures pratiques pour des trunks VoIP sécurisés et évolutifs

  • Utilisez TLS pour SIP (ajoutez protocol=tls dans les transports) pour chiffrer la signalisation.
  • Implémentez des ACL dans pjsip.conf pour restreindre les IP.
  • Surveillez avec des outils comme sngrep pour l’analyse du trafic SIP.
  • Évoluez avec plusieurs trunks pour l’équilibrage de charge dans les environnements multi-Asterisk.

En suivant ce guide d’interconnexion Asterisk PJSIP, vous aurez un trunk VoIP robuste opérationnel.

Comprendre et utiliser Kamailio partie 1

Il y a quelques semaines de cela je me suis lancé dans un projet de créer un SBC (Session Border Controller) avec des logiciels open source pour le fun et le profit; Dans l’espoir de pouvoir commercialiser des offres de téléphonie mais aussi plus largement pour apprendre et surtout comprendre le fonctionnement de la téléphonie (fixe dans un premier temps).

Dans cette séries d’articles, je vais vous présenter les outils qui affèrent à la VoIP (Voice over IP) et