SSD Nodes Learn 🎉 VPS dès $5.50/mois
Guides Matt ConnorPar Matt Connor

Serveur VoIP auto-hébergé : Asterisk ou FreePBX

Installez Asterisk ou FreePBX sur un VPS avec trunk SIP, ports RTP et règles firewall. Comprenez comment limiter les scanners et éviter le toll fraud.

Ce qu’est un serveur VoIP auto-hébergé

Un serveur VoIP auto-hébergé est un serveur SIP exécuté sur un VPS que vous contrôlez. Vos appels sont donc acheminés par votre propre machine, et non par un service de téléphonie hébergé. La VoIP (voix sur IP) transporte la voix sous forme de paquets UDP. Le SIP (session initiation protocol) assure la signalisation qui établit et termine un appel. L’audio ne transite pas par SIP. C’est la principale cause des problèmes décrits ci-dessous.

Quatre éléments sont nécessaires pour obtenir un système fonctionnel.

  • Le logiciel PBX (private branch exchange). Asterisk est le choix habituel. Il contient les extensions et le dialplan.
  • Les endpoints. Il peut s’agir de téléphones de bureau ou de softphones qui s’enregistrent auprès du PBX avec un nom d’utilisateur et un secret.
  • Le SIP trunk. Il s’agit d’un compte payant auprès d’un fournisseur qui vous connecte au réseau téléphonique public et vous loue de vrais numéros de téléphone.
  • Le chemin média. Les flux RTP (real-time transport protocol) transportent l’audio sur leurs propres ports UDP.

Auto-héberger le PBX ne signifie pas auto-héberger les numéros de téléphone. Les numéros sont fournis par un opérateur, et vous payez toujours chaque numéro ainsi que les minutes consommées. Ce que vous contrôlez, c’est le routage des appels, la messagerie vocale, les enregistrements et la liste des extensions. Vous êtes également responsable de la sécurité d’un service que des attaquants ciblent pour gagner de l’argent.

Quels ports un serveur VoIP auto-hébergé doit-il utiliser ?

La signalisation SIP utilise le port 5060 en UDP et en TCP, ainsi que le port 5061 pour SIP over TLS (transport layer security). Ces ports servent uniquement à établir les appels. L’audio de chaque appel utilise un flux UDP distinct, envoyé vers un port de la plage RTP. Asterisk fournit un exemple rtp.conf qui définit rtpstart=10000 et rtpend=20000. Les valeurs par défaut intégrées sont 5000 et 31000. Chaque appel utilise deux ports de cette plage : un pour RTP et un pour RTCP (RTP control protocol).

Cette séparation est la principale cause d’échec des premières configurations. L’appel aboutit, les deux téléphones indiquent qu’il est répondu, mais aucun interlocuteur n’entend l’autre, car le pare-feu autorise 5060 et bloque tous les paquets RTP. La signalisation et les médias utilisent des flux distincts. Ils nécessitent donc des règles de pare-feu distinctes. Si cette distinction est nouvelle pour vous, consultez le fonctionnement des ports et des sockets en écoute sous Linux avant d’ouvrir quoi que ce soit.

Réduisez la plage avant de l’ouvrir. Vingt mille ports sont largement suffisants pour un petit système. Deux ports par appel signifient qu’une plage de deux cents ports permet de gérer cent appels simultanés.

[general]
rtpstart=10000
rtpend=10200

Appliquez cette configuration avec sudo asterisk -rx "core reload".

Faut-il installer Asterisk ou FreePBX ?

Asterisk est le moteur. Vous le configurez avec des fichiers texte dans /etc/asterisk et vous écrivez vous-même le dialplan. FreePBX est une interface web écrite en PHP et JavaScript. Elle s’appuie sur Asterisk, génère ces fichiers à votre place et ajoute des modules pour la messagerie vocale et les files d’attente d’appels.

Sur un VPS, la différence importante concerne la maîtrise de la machine. En août 2026, l’installateur officiel de FreePBX 17 attend un système Debian 12 standard. Il installe Asterisk, un serveur web, un serveur de base de données et PHP. Si vous le lancez sur une machine qui héberge déjà d’autres services, le résultat sera probablement mauvais. Réservez un VPS à FreePBX.

wget https://github.com/FreePBX/sng_freepbx_debian_install/raw/master/sng_freepbx_debian_install.sh -O /tmp/sng_freepbx_debian_install.sh
sudo bash /tmp/sng_freepbx_debian_install.sh

Le journal d’installation est écrit dans /var/log/pbx/freepbx17-install.log. C’est le premier fichier à consulter lorsque le script s’arrête prématurément.

FreePBX gère les fichiers de configuration qu’il génère. Si vous modifiez pjsip.conf manuellement sur une machine FreePBX, votre modification disparaîtra la prochaine fois que l’interface web réécrira ce fichier. FreePBX lit des fichiers distincts dont le nom contient _custom pour la configuration écrite manuellement. Il ne modifie pas ces fichiers.

Le compromis est clair. FreePBX fournit une interface graphique et expose une page de connexion de votre système téléphonique sur Internet. Asterisk seul n’a aucune interface web. Chaque paramètre correspond à une directive documentée, lisible dans un fichier et conservable dans git. Si vous installez FreePBX, restreignez son port web à votre propre adresse IP ou utilisez-le via un VPN, car une interface d’administration de PBX est une cible qui permet d’accéder directement à des fonctions liées à l’argent.

Note de version, valable en août 2026 : Asterisk 22 est la version actuelle avec support à long terme. Elle a été publiée en octobre 2024 et reçoit des correctifs de sécurité jusqu’en octobre 2028. Asterisk 23 est la version standard. Ubuntu 24.04 fournit Asterisk 20.6.0 dans le dépôt universe.

Installer Asterisk sur Ubuntu 24.04

Le paquet de la distribution est la méthode la plus rapide. Ubuntu le corrige et le démarre automatiquement avec systemd.

sudo apt update
sudo apt install -y asterisk
sudo asterisk -rx "core show version"

La compilation depuis les sources vous fournit plutôt la version actuelle avec support à long terme.

sudo apt update
sudo apt install -y build-essential wget
cd /usr/local/src
sudo wget https://downloads.asterisk.org/pub/telephony/asterisk/asterisk-22-current.tar.gz
sudo tar -xzf asterisk-22-current.tar.gz
cd asterisk-22.*
sudo contrib/scripts/install_prereq install
sudo ./configure
sudo make menuselect
sudo make -j"$(nproc)"
sudo make install
sudo make samples
sudo make config
sudo ldconfig

install_prereq install installe les dépendances de compilation pour votre distribution, tandis que install_prereq test affiche les commandes qu’il exécuterait sans rien modifier. make menuselect ouvre le sélecteur de modules. C’est là que vous activez codec_opus dans la section Codec Translators. Exécutez make samples uniquement sur une installation neuve, car cette commande écrit la configuration d’exemple dans /etc/asterisk. make config installe le script d’initialisation dans /etc/init.d/asterisk. systemd l’exécute via sa couche de compatibilité SysV. sudo systemctl enable --now asterisk fonctionne donc ensuite.

Quelle que soit la méthode choisie, sudo asterisk -rvvv se connecte au daemon en cours d’exécution et vous fournit la CLI. Exécuter core show version à cet endroit affiche ce qui a réellement été installé.

Configurer un trunk SIP et un poste

PJSIP est le channel driver SIP utilisé par les versions actuelles d’Asterisk. Sa configuration se trouve dans /etc/asterisk/pjsip.conf et repose sur de petites sections typées qui se référencent par leur nom. Des sections de types différents peuvent partager le même nom. C’est pourquoi chaque bloc ci-dessous s’appelle mytrunk.

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

[mytrunk]
type=registration
outbound_auth=mytrunk
server_uri=sip:sip.example.com
client_uri=sip:1234567890@sip.example.com
retry_interval=60

[mytrunk]
type=auth
auth_type=userpass
username=1234567890
password=REPLACE_WITH_A_LONG_RANDOM_SECRET

[mytrunk]
type=aor
contact=sip:sip.example.com:5060

[mytrunk]
type=endpoint
context=from-trunk
disallow=all
allow=ulaw
outbound_auth=mytrunk
aors=mytrunk

[mytrunk]
type=identify
endpoint=mytrunk
match=sip.example.com

L’objet registration envoie le REGISTER qui indique à votre fournisseur où acheminer vos appels. L’objet identify permet d’associer un appel reçu du fournisseur à cet endpoint selon son adresse source. Un fournisseur publie généralement plusieurs adresses à renseigner à cet endroit. L’outbound registration et l’endpoint sont volontairement des objets distincts : le premier indique au fournisseur où vous joindre, tandis que le second détermine le traitement des appels.

Un téléphone de bureau nécessite trois objets supplémentaires.

[6001]
type=endpoint
context=internal
disallow=all
allow=ulaw
auth=auth6001
aors=6001
direct_media=no

[auth6001]
type=auth
auth_type=userpass
username=6001
password=REPLACE_WITH_A_LONG_RANDOM_SECRET

[6001]
type=aor
max_contacts=1

direct_media=no maintient Asterisk dans le chemin média. Si vous le supprimez, Asterisk essaiera de faire envoyer directement le RTP entre les deux endpoints. Cela échoue lorsqu’un téléphone se trouve derrière le NAT (network address translation) d’un routeur domestique. Le secret ne doit jamais être identique au numéro de l’extension. L’exemple fourni utilise password=6001 pour l’extension 6001 afin de rester lisible, et les scanners essaient précisément ce type de valeur en premier.

Le dialplan de /etc/asterisk/extensions.conf détermine les opérations autorisées dans chaque contexte.

[internal]
exten => 6001,1,Dial(PJSIP/6001,20)
exten => _9X.,1,Dial(PJSIP/${EXTEN:1}@mytrunk,60)

[from-trunk]
exten => 1234567890,1,Dial(PJSIP/6001,20)
same => n,Hangup()

Ces deux contextes constituent une frontière de sécurité. from-trunk traite les appels reçus du fournisseur et peut uniquement faire sonner l’extension 6001. Il ne peut pas accéder au pattern _9X.. Un appel externe ne peut donc pas utiliser votre trunk pour émettre un nouvel appel. Si vous fusionnez les contextes, vous créez le chemin classique de la fraude téléphonique : un inconnu appelle votre numéro, votre dialplan émet un appel avec votre compte, et vous en payez le coût.

Appliquez la configuration et vérifiez-la.

sudo asterisk -rx "pjsip reload"
sudo asterisk -rx "pjsip show registrations"
sudo asterisk -rx "pjsip show endpoints"

pjsip show registrations doit afficher mytrunk avec le statut Registered. Rejected signifie que le fournisseur a refusé vos identifiants. Unregistered signifie que votre REGISTER reste sans réponse. Vérifiez alors le firewall.

Règles de pare-feu pour SIP et RTP

La signalisation et les flux média doivent être traités différemment, car ils ne présentent pas les mêmes risques. Limitez le port 5060 aux adresses réellement utilisées par votre fournisseur et aux réseaux auxquels vos téléphones sont connectés.

sudo ufw allow proto udp from 203.0.113.10 to any port 5060
sudo ufw allow proto tcp from 203.0.113.10 to any port 5060
sudo ufw allow 10000:10200/udp
sudo ufw status verbose

La plage RTP est plus difficile à restreindre, car les flux média arrivent souvent d’une adresse différente de celle de la signalisation. Demandez à votre fournisseur les sous-réseaux utilisés pour les flux média et limitez-les à ces sous-réseaux s’il les publie. Conservez une plage seulement assez large pour couvrir votre heure la plus chargée. Les politiques par défaut, l’ordre des règles et le reste du modèle ufw sont présentés dans le guide de base du pare-feu ufw pour un VPS.

Vérifiez également IPv6. Si IPV6=no est défini dans /etc/default/ufw, ufw ne filtre pas du tout IPv6. Un daemon lié à :: est donc accessible via IPv6 sans qu’aucune des règles ci-dessus ne s’applique. Ouvrir des ports IPv6 avec ufw explique les différences entre les deux familles. La plupart des fournisseurs proposent également un pare-feu réseau séparé dans le control panel. Celui-ci est appliqué avant que vos paquets n’atteignent le VPS. Un port doit donc être ouvert aux deux endroits.

Le brute force SIP et la fraude à la consommation téléphonique ne sont pas des problèmes facultatifs

Exposez le port 5060 sur une adresse publique et les scans commencent. Le schéma est régulier : des requêtes REGISTER et INVITE provenant de nombreuses adresses source essaient des numéros de poste courants avec des secrets courants. Asterisk consigne chaque échec, sous cette forme.

Request 'REGISTER' from '<sip:1000@198.51.100.20>' failed for '198.51.100.20:5060' (callid: 5f1a5c0d) - No matching endpoint found

La raison pour laquelle ce problème mérite de vrais efforts est financière. Un poste compromis sert à passer des appels internationaux coûteux, souvent vers des numéros surtaxés qui reversent une commission à l’attaquant. C’est vous qui recevez la facture, car les appels utilisent vos identifiants. Ces tentatives s’exécutent à la vitesse d’une machine et ont généralement lieu pendant la nuit.

Six contrôles sont obligatoires, et non de simples mesures de durcissement facultatives.

  • Ne créez jamais un poste dont le secret est son propre numéro ou un mot court. Générez-en un avec openssl rand -base64 24, puis collez-le.
  • Désactivez les appels entrants anonymes. PJSIP refuse par défaut les appels non identifiés et ne les accepte que si vous créez un endpoint nommé anonymous. N’en créez pas.
  • Gardez le contexte du trunk séparé de tout contexte qui peut passer des appels sortants, comme indiqué plus haut.
  • Restreignez la signalisation par adresse source, à la fois dans ufw et dans le pare-feu réseau de votre fournisseur.
  • Définissez un plafond de dépenses avec le fournisseur de votre trunk SIP et désactivez les destinations internationales que vous n’appelez jamais. C’est le seul contrôle qui limite les pertes lorsque les autres échouent.
  • Exécutez fail2ban sur le journal Asterisk.

Asterisk peut également générer un événement de sécurité après plusieurs requêtes non correspondantes provenant d’une même adresse. La section [global] de pjsip.conf utilise unidentified_request_count, dont la valeur par défaut est 5, et unidentified_request_period, dont la valeur par défaut est de 5 secondes. Ensemble, ces paramètres signifient que cinq requêtes non correspondantes provenant d’une même adresse en l’espace de cinq secondes génèrent un événement de sécurité sur lequel fail2ban peut agir.

Interdire les scanners avec fail2ban

fail2ban fournit déjà une jail asterisk. Elle couvre les ports 5060 et 5061, lit /var/log/asterisk/messages et utilise maxretry = 10 par défaut. La jail reste désactivée tant que vous ne l’activez pas dans /etc/fail2ban/jail.local.

[asterisk]
enabled = true
maxretry = 5
findtime = 600
bantime = 86400
sudo systemctl restart fail2ban
sudo fail2ban-client status asterisk

Un résultat correct indique le fichier de log de la jail et le nombre d’adresses actuellement bannies. Sur un port 5060 public, ce nombre cesse d’être nul en moins d’une journée. Le filtre fourni détecte les messages No matching endpoint found ci-dessus. Il détecte également les lignes SecurityEvent structurées d’Asterisk. Ces événements sont envoyés vers un canal de log distinct, commenté dans /etc/asterisk/logger.conf. Activez-le à cet endroit, puis ajoutez le fichier à logpath de la jail si vous souhaitez les prendre en compte.

[logfiles]
console => notice,warning,error
messages.log => notice,warning,error
security.log => security

Rechargez le logger avec sudo asterisk -rx "logger reload". Le filtre inclut également un journalmatch pour asterisk.service. Vous pouvez donc utiliser un backend journal si vous préférez ne pas conserver de fichiers de log. L’installation, la structure jail.local et le déblocage d’une adresse que vous avez verrouillée sont expliqués dans le guide fail2ban pour Ubuntu 24.04.

Latence et choix du codec sur un VPS distant

La latence dépend de la distance géographique et vous ne pouvez pas la supprimer par la configuration. La recommandation ITU-T G.114 est de maintenir la latence aller simple sous 150 ms pour une conversation normale. Elle considère qu’une latence allant jusqu’à environ 400 ms reste utilisable. L’audio d’un téléphone est envoyé vers votre VPS, puis vers votre fournisseur de trunk. Un VPS situé dans une mauvaise région effectue donc deux fois ce trajet. Placez-le près des téléphones ou du fournisseur. Si ces deux choix s’opposent, privilégiez la proximité des téléphones, car cette liaison passe généralement par Internet grand public, où la gigue est la plus importante.

Le choix du codec détermine la bande passante nécessaire par appel. Chaque codec présenté ici envoie un paquet toutes les 20 ms, soit 50 paquets par seconde. Chaque paquet contient 40 octets d’en-têtes IP, UDP et RTP, en plus de la charge utile audio.

ChartBandwidth per concurrent call, one direction, 20 ms packets
The data behind this chart
[
  {
    "label": "G.711 ulaw",
    "payload_kbps": 64,
    "ip_kbps": 80
  },
  {
    "label": "G.722",
    "payload_kbps": 64,
    "ip_kbps": 80
  },
  {
    "label": "Opus at 24 kbps",
    "payload_kbps": 24,
    "ip_kbps": 40
  },
  {
    "label": "G.729",
    "payload_kbps": 8,
    "ip_kbps": 24
  }
]

G.711 ulaw est le codec par défaut sur la plupart des trunks. Sa charge utile est de 64 kbps. Avec les en-têtes, un appel en cours consomme 80 kbps dans chaque direction. Opus à 24 kbps utilise 40 kbps. G.729 réduit cette valeur à 24 kbps, au prix d’une qualité audio et d’un temps CPU moindres. Ces chiffres résultent d’un calcul sur les en-têtes, et non de mesures : débit de la charge utile plus 40 octets par paquet à 50 paquets par seconde. L’encapsulation Ethernet ou VLAN ajoute une faible quantité de données sur le réseau.

Le transcodage consomme du CPU. Si vos téléphones et votre trunk utilisent tous deux ulaw, n’autorisez que ulaw. Asterisk transmet alors l’audio sans le modifier. Opus résiste bien aux pertes sur les liaisons réseau, mais le transcodage entre Opus et G.711 nécessite le module externe codec_opus. Vous le sélectionnez dans make menuselect. Ce module n’est pas compilé par défaut.

Ce qui échoue et le message affiché

L’appel aboutit, mais personne n’entend rien. Aucun paquet RTP n’arrive. Vérifiez que la plage définie dans rtp.conf correspond à celle que vous avez ouverte dans le firewall, puis surveillez les paquets avec sudo tcpdump -ni any udp portrange 10000-10200 pendant un appel. L’absence totale de paquets signifie que votre firewall ou celui du réseau de votre fournisseur les bloque.

Le son ne passe que dans un sens. Une partie envoie le RTP vers une adresse qui ne peut pas le recevoir. Le problème concerne donc l’adresse, pas le port. Si votre VPS utilise directement son adresse publique sur son interface, aucune gestion du NAT n’est nécessaire. Si le fournisseur attribue au VPS une adresse privée avec une correspondance publique un-à-un, définissez l’adresse publique sur le transport et indiquez votre plage privée dans local_net.

[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0
local_net=10.0.0.0/8
external_media_address=198.51.100.5
external_signaling_address=198.51.100.5

No matching endpoint found dans le journal. La requête ne correspond à aucun endpoint selon l’adresse IP ou le nom d’utilisateur. Depuis un scanner, ce comportement est normal et fail2ban le prendra en charge. Depuis votre propre fournisseur, cela signifie que la section identify ne contient pas l’adresse depuis laquelle il vous appelle.

L’état de l’enregistrement est Rejected. Le fournisseur a refusé les identifiants de votre section auth. Exécutez pjsip set logger on dans la CLI, surveillez un REGISTER et la réponse correspondante, puis comparez client_uri et username avec les valeurs fournies par le fournisseur.

Le journal ne contient aucune information utile. Par défaut, Asterisk écrit dans messages.log les messages de niveau notice et supérieur. Augmentez ce niveau avec core set verbose 4 et pjsip set logger on pendant la reproduction du problème, puis désactivez les deux paramètres, car le SIP logger écrit chaque paquet.

Avant de l’exposer

Un PBX n’est pas un service comme les autres que vous auto-hébergez. Une application web défaillante vous fait perdre une page. Un PBX défaillant peut générer une facture téléphonique en quelques heures, pendant que vous dormez. Exécutez-le sur un VPS dédié, limitez le port 5060 aux adresses connues, attribuez un secret aléatoire à chaque extension et définissez un plafond de dépenses sur le compte trunk. Le reste du serveur doit respecter le même niveau de sécurité de base que tout serveur exposé, comme l’explique cet aperçu de la sécurité réelle de l’hébergement VPS.

FAQ

Quels ports dois-je ouvrir pour un serveur VoIP auto-hébergé ?

Le port 5060 pour la signalisation SIP sur UDP et TCP, le port 5061 si vous utilisez SIP sur TLS, ainsi qu’une plage de ports UDP pour les flux RTP. L’exemple de configuration d’Asterisk rtp.conf utilise les ports 10000 à 20000, et les valeurs par défaut intégrées sont 5000 à 31000. Chaque appel consomme deux ports de la plage. Une plage de deux cents ports gère donc cent appels simultanés. Ouvrez la plage RTP en UDP. Limitez le port 5060 aux adresses de votre fournisseur et à vos propres réseaux, au lieu de l’ouvrir à tout le monde.

Dois-je installer Asterisk seul ou utiliser FreePBX ?

Installez Asterisk seul si vous voulez réduire la surface d’attaque, conserver les fichiers de configuration dans git et écrire vous-même le dialplan. Installez FreePBX si vous voulez une interface graphique pour les extensions, la messagerie vocale et les files d’attente d’appels. En août 2026, l’installateur de FreePBX 17 attend une machine Debian 12 vierge et installe Asterisk, un serveur web, un serveur de bases de données et PHP. Prévoyez donc un VPS dédié. FreePBX régénère les fichiers de configuration qu’il gère. Les modifications manuelles doivent donc être effectuées dans ses fichiers _custom.

Pourquoi n’y a-t-il pas de son après l’établissement de l’appel ?

La signalisation a fonctionné, mais pas le flux média. SIP a établi l’appel sur le port 5060. L’audio utilise un flux UDP distinct vers un port de la plage RTP, et un équipement bloque ce flux. Vérifiez que la plage définie dans rtp.conf correspond à celle autorisée par votre firewall. Vérifiez aussi le firewall réseau de votre fournisseur, ainsi que celui du serveur. Exécutez sudo tcpdump -ni any udp portrange 10000-10200 pendant un appel. L’absence de paquets signifie qu’ils sont bloqués avant d’arriver.

Comment arrêter les attaques par brute force contre SIP et la fraude téléphonique ?

Attribuez à chaque extension un secret long et aléatoire. N’utilisez jamais un secret identique au numéro de l’extension. Séparez le context utilisé par votre trunk de tout context autorisant les appels sortants. Ainsi, un appel entrant ne pourra pas effectuer un nouvel appel sortant avec votre compte. Limitez le port 5060 aux adresses de votre fournisseur. Activez la jail asterisk dans fail2ban. Elle lit /var/log/asterisk/messages et bannit les adresses qui provoquent No matching endpoint found échecs. Définissez ensuite un plafond de dépenses et bloquez les destinations internationales inutilisées auprès de votre fournisseur. C’est le seul contrôle qui limite les pertes si les autres mesures échouent.

Un VPS situé dans une région éloignée dégrade-t-il la qualité des appels ?

Oui. L’audio parcourt deux segments : du téléphone au VPS, puis du VPS au fournisseur trunk. La recommandation ITU-T G.114 est de maintenir le délai aller simple sous 150 ms. Un VPS mal situé peut consommer la majeure partie de ce budget avec la distance uniquement. Choisissez une région proche des téléphones, car ce segment passe généralement par une connexion internet grand public, où la gigue est la plus importante. Le choix du codec ne corrige pas le délai. Il modifie seulement la bande passante. G.729 réduit donc le volume de données, mais ne corrigera pas un chemin de 200 ms.

#voip#asterisk#freepbx#sip#auto-hébergement