Zelf een VoIP-server hosten met Asterisk en FreePBX
Bouw uw eigen VoIP-server met Asterisk of FreePBX op een VPS. Leer hoe u SIP-trunks configureert, RTP-poorten opent en firewallregels instelt om toll fraud effectief te voorkomen.
Wat een self-hosted VoIP-server is
Een self-hosted VoIP-server is een SIP-server die draait op een VPS die u beheert. Hierdoor wordt uw telefoonverkeer gerouteerd door uw eigen machine in plaats van door een gehoste telefoondienst. VoIP (voice over IP) verstuurt spraak als UDP-pakketten. SIP (session initiation protocol) is de signalering die een gesprek opzet en beëindigt. De audio verloopt niet via SIP, en dat ene feit veroorzaakt het merendeel van de onderstaande problemen.
Vier onderdelen vormen een werkend systeem.
- De PBX-software (private branch exchange). Asterisk is de gebruikelijke keuze. Deze beheert de extensies en het dialplan.
- De endpoints. Bureautelefoons of softphones die zich bij de PBX registreren met een gebruikersnaam en een wachtwoord.
- De SIP-trunk. Een betaald account bij een provider die u verbindt met het openbare telefoonnetwerk en u echte telefoonnummers verhuurt.
- Het mediapad. RTP-stromen (real-time transport protocol) die de audio over hun eigen UDP-poorten transporteren.
Het zelf hosten van de PBX betekent niet dat u zelf telefoonnummers host. Nummers zijn afkomstig van een provider en u betaalt nog steeds per nummer en per minuut. Wat u in eigen beheer heeft, is de gespreksroutering, de voicemail, de opnames en de extensielijst. U bent ook verantwoordelijk voor de beveiliging van een dienst die door kwaadwillenden wordt aangevallen voor financieel gewin.
Welke poorten heeft een zelfgehoste VoIP-server nodig?
SIP-signalisatie gebruikt poort 5060 voor UDP en TCP, en poort 5061 voor SIP over TLS (transport layer security). Deze poorten verzorgen uitsluitend het opzetten van gesprekken. De audio van elk gesprek is een afzonderlijke UDP-stroom, die wordt verzonden naar een poort uit het RTP-bereik. Asterisk levert een voorbeeld rtp.conf mee waarin rtpstart=10000 en rtpend=20000 worden ingesteld; de gecompileerde standaardwaarden zijn 5000 en 31000. Elk gesprek gebruikt twee poorten uit dit bereik: één voor RTP en één voor RTCP (RTP control protocol).
Deze splitsing is waar de meeste eerste pogingen mislukken. Het gesprek wordt verbonden, beide telefoons geven aan dat er is opgenomen, maar aan beide kanten is niets te horen. Dit komt doordat de firewall poort 5060 toestaat, maar elk RTP-pakket blokkeert. Signalisatie en media zijn afzonderlijke stromen en vereisen daarom aparte firewallregels. Als dit onderscheid nieuw voor u is, is hoe poorten en listening sockets werken op Linux het lezen waard voordat u poorten opent.
Verklein het bereik voordat u het opent. Twintigduizend poorten is veel meer dan een klein systeem nodig heeft. Twee poorten per gesprek betekent dat een bereik van tweehonderd poorten honderd gelijktijdige gesprekken ondersteunt.
[general]
rtpstart=10000
rtpend=10200Pas dit toe met sudo asterisk -rx "core reload".
Moet u Asterisk of FreePBX installeren?
Asterisk is de engine. U configureert deze met tekstbestanden in /etc/asterisk en u schrijft het dialplan zelf. FreePBX is een webinterface geschreven in PHP en JavaScript die boven op Asterisk draait, deze bestanden voor u genereert en modules toevoegt voor voicemail en wachtrijen.
Het verschil dat op een VPS van belang is, is het beheer van de machine. Sinds augustus 2026 verwacht het officiële FreePBX 17-installatieprogramma een standaard Debian 12-systeem, en het installeert Asterisk, een webserver, een databaseserver en PHP. Richt dit op een server die al andere diensten draait en het resultaat zal tegenvallen. Geef FreePBX een eigen VPS.
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.shHet installatielogboek komt terecht in /var/log/pbx/freepbx17-install.log; dit is de eerste plek om te kijken wanneer het script voortijdig stopt.
FreePBX beheert de configuratiebestanden die het genereert. Bewerk pjsip.conf handmatig op een FreePBX-systeem en uw wijziging verdwijnt zodra de GUI het bestand opnieuw schrijft. FreePBX leest afzonderlijke bestanden met _custom in de naam voor handmatige configuratie; deze bestanden laat het ongemoeid.
De eerlijke afweging is als volgt. FreePBX biedt u een GUI en plaatst een inlogpagina voor uw telefoonsysteem op het openbare internet. Kale Asterisk heeft helemaal geen webinterface en elke instelling is een gedocumenteerde richtlijn die u in een bestand kunt lezen en in git kunt bijhouden. Als u FreePBX installeert, beperk de webpoort dan tot uw eigen adres of benader deze via een VPN, omdat een beheer-GUI voor een PBX een doelwit is met een directe route naar financieel gewin.
Versienotitie, correct per augustus 2026: Asterisk 22 is de huidige long-term support-release, gepubliceerd in oktober 2024 en voorzien van beveiligingsupdates tot oktober 2028. Asterisk 23 is de standaard release. Ubuntu 24.04 bevat Asterisk 20.6.0 in de universe-repository.
Asterisk installeren op Ubuntu 24.04
Het distributiepakket is de snelste methode. Ubuntu voorziet in patches en de service start automatisch onder systemd.
sudo apt update
sudo apt install -y asterisk
sudo asterisk -rx "core show version"Bouwen vanuit de broncode geeft u toegang tot de huidige long term support release.
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 ldconfiginstall_prereq install haalt de build-dependencies voor uw distributie op en install_prereq test toont de commando's die zouden worden uitgevoerd zonder wijzigingen aan te brengen. make menuselect opent de module-kiezer, waar u codec_opus inschakelt onder Codec Translators. Voer make samples alleen uit op een schone installatie, aangezien dit de voorbeeldconfiguratie naar /etc/asterisk schrijft. make config installeert het init-script op /etc/init.d/asterisk, en systemd stuurt dit aan via de SysV-compatibiliteitslaag, waardoor sudo systemctl enable --now asterisk daarna werkt.
Welke methode u ook heeft gekozen, sudo asterisk -rvvv koppelt aan de actieve daemon en geeft u toegang tot de CLI. Het uitvoeren van core show version in de CLI toont wat u daadwerkelijk heeft geïnstalleerd.
Een SIP-trunk en één extensie configureren
PJSIP is de SIP-kanaaldriver in de huidige versie van Asterisk. De configuratie bevindt zich in /etc/asterisk/pjsip.conf en is opgebouwd uit kleine, getypeerde secties die naar elkaar verwijzen op naam. Secties van verschillende typen kunnen dezelfde naam delen; daarom heet elk blok hieronder 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.comHet registration-object verstuurt de REGISTER-aanvraag die uw provider vertelt waar uw gesprekken moeten worden afgeleverd. Het identify-object bepaalt hoe een gesprek dat binnenkomt van de provider wordt gekoppeld aan dit eindpunt op basis van het bronadres; een provider publiceert doorgaans meerdere adressen die u daar kunt opgeven. Uitgaande registratie en het eindpunt zijn bewust gescheiden objecten: de een vertelt de provider waar u bent, de ander bepaalt wat er met de gesprekken gebeurt.
Een bureautoestel heeft drie extra objecten nodig.
[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=1direct_media=no houdt Asterisk in het mediapad. Laat u dit weg, dan zal Asterisk proberen de twee eindpunten RTP rechtstreeks naar elkaar te laten sturen. Dit faalt wanneer een toestel zich achter NAT (network address translation) op een thuisrouter bevindt. Zorg dat het wachtwoord nooit gelijk is aan het extensienummer. Het voorbeeld hierboven gebruikt password=6001 voor extensie 6001 om het leesbaar te houden, maar aanvallers proberen precies dat patroon als eerste.
Het dialplan in /etc/asterisk/extensions.conf bepaalt wat elke context mag doen.
[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()Deze twee contexten vormen een beveiligingsgrens. from-trunk verwerkt gesprekken die binnenkomen van de provider en kan alleen extensie 6001 laten overgaan. Het kan het _9X.-patroon niet bereiken, waardoor een gesprek van buitenaf niet via uw trunk naar buiten kan bellen. Voegt u de contexten samen, dan creëert u de klassieke route voor toll fraud: een vreemde belt uw nummer, uw dialplan belt uit via uw account, en u betaalt de rekening.
Pas de configuratie toe en controleer deze.
sudo asterisk -rx "pjsip reload"
sudo asterisk -rx "pjsip show registrations"
sudo asterisk -rx "pjsip show endpoints"pjsip show registrations hoort mytrunk weer te geven met de status Registered. Rejected betekent dat de provider uw inloggegevens heeft geweigerd. Unregistered betekent dat uw REGISTER onbeantwoord blijft; controleer in dat geval de firewall.
Firewallregels voor SIP en RTP
Signalerings- en mediagegevens vereisen een verschillende aanpak omdat ze uiteenlopende risico's met zich meebrengen. Beperk poort 5060 tot de adressen die uw provider daadwerkelijk gebruikt en tot de netwerken waar uw telefoons zich bevinden.
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 verboseHet RTP-bereik is het deel dat u minder ver kunt inperken, omdat media vaak vanaf een ander adres binnenkomt dan de signalering. Vraag uw provider naar hun mediasubnetten en beperk de toegang hiertoe indien zij deze publiceren. Houd het bereik niet groter dan noodzakelijk voor uw drukste uren. Standaardbeleid, regelvolgorde en de rest van het ufw-model worden behandeld in de basisgids voor de ufw-firewall op een VPS.
Controleer ook IPv6. Als IPV6=no is ingesteld in /etc/default/ufw, filtert ufw IPv6 helemaal niet. Hierdoor is een daemon die gebonden is aan :: bereikbaar via IPv6 zonder dat de bovenstaande regels worden toegepast. Poorten openen voor IPv6 met ufw legt uit hoe de twee families van elkaar verschillen. De meeste providers bieden ook een afzonderlijke netwerkfirewall in het configuratiescherm. Deze wordt afgedwongen voordat uw pakketten de VPS bereiken, dus een poort moet op beide locaties worden geopend.
SIP brute force en toll fraud zijn geen optionele problemen
Plaats 5060 op een publiek adres en de scans beginnen direct. Het patroon is constant: REGISTER- en INVITE-verzoeken vanaf vele bronadressen, waarbij geprobeerd wordt in te loggen op veelvoorkomende extensienummers met veelvoorkomende wachtwoorden. Asterisk logt elke mislukte poging en de regel ziet er als volgt uit.
Request 'REGISTER' from '<sip:1000@198.51.100.20>' failed for '198.51.100.20:5060' (callid: 5f1a5c0d) - No matching endpoint foundDe reden dat dit serieuze aandacht vereist, is geld. Een gestolen extensie wordt gebruikt om dure internationale gesprekken te voeren, vaak naar betaalnummers die de aanvaller een deel van de opbrengst opleveren. De rekening is voor u, omdat de gesprekken gebruikmaakten van uw inloggegevens. Dit proces verloopt op machinesnelheid en vindt meestal 's nachts plaats.
Zes maatregelen zijn verplicht in plaats van optioneel voor een goede beveiliging.
- Maak nooit een extensie aan waarvan het wachtwoord gelijk is aan het nummer zelf of een kort woord. Genereer er een met
openssl rand -base64 24en plak deze in de configuratie. - Laat anonieme inkomende gesprekken uitgeschakeld. PJSIP weigert standaard niet-geïdentificeerde gesprekken en accepteert deze alleen als u een endpoint aanmaakt genaamd
anonymous. Maak deze niet aan. - Houd de trunk-context gescheiden van elke context die naar buiten kan bellen, zoals hierboven getoond.
- Beperk signalering op basis van bronadres, zowel in ufw als in de netwerkfirewall van uw provider.
- Stel een bestedingslimiet in bij uw SIP-trunkprovider en schakel de internationale bestemmingen uit waar u nooit naartoe belt. Dit is de enige maatregel die het verlies beperkt wanneer de andere maatregelen falen.
- Draai fail2ban op het Asterisk-logbestand.
Asterisk kan ook een beveiligingsgebeurtenis genereren na herhaalde niet-overeenkomende verzoeken vanaf één adres. De sectie [global] van pjsip.conf gebruikt unidentified_request_count, dat standaard op 5 staat, en unidentified_request_period, dat standaard op 5 seconden staat. Samen betekenen deze dat vijf niet-overeenkomende verzoeken vanaf één adres binnen vijf seconden een beveiligingsgebeurtenis produceren waar fail2ban op kan reageren.
Blokkeer scanners met fail2ban
fail2ban bevat standaard al een asterisk jail. Deze dekt poort 5060 en 5061, leest /var/log/asterisk/messages en gebruikt maxretry = 10 als standaardinstelling. De jail blijft uitgeschakeld totdat u deze activeert in /etc/fail2ban/jail.local.
[asterisk]
enabled = true
maxretry = 5
findtime = 600
bantime = 86400sudo systemctl restart fail2ban
sudo fail2ban-client status asteriskEen correct resultaat toont het logbestand van de jail en het aantal momenteel geblokkeerde adressen. Op een publieke poort 5060 zal dat aantal binnen een dag niet meer op nul staan. Het meegeleverde filter komt overeen met de bovenstaande No matching endpoint found meldingen en matcht ook de gestructureerde SecurityEvent regels van Asterisk. Deze gebeurtenissen worden naar een apart logkanaal geschreven dat in /etc/asterisk/logger.conf is uitgeschakeld; schakel dit daar in en voeg het bestand toe aan de logpath van de jail als u deze wilt gebruiken.
[logfiles]
console => notice,warning,error
messages.log => notice,warning,error
security.log => securityHerlaad de logger met sudo asterisk -rx "logger reload". Het filter bevat ook een journalmatch voor asterisk.service, waardoor een journal-backend werkt als u liever geen logbestanden bijhoudt. Installatie, de structuur van jail.local en het deblokkeren van een adres dat u heeft buitengesloten, worden behandeld in de fail2ban-handleiding voor Ubuntu 24.04.
Latentie en codec-keuze op een verre VPS
Vertraging wordt bepaald door de geografische afstand en is niet via configuratie weg te nemen. ITU-T G.114 adviseert om de eenrichtingsvertraging onder de 150 ms te houden voor normale gesprekken en beschouwt waarden tot ongeveer 400 ms als nog bruikbaar. Audio van een telefoon gaat naar uw VPS en vervolgens naar uw trunk-provider; een VPS in de verkeerde regio betaalt die reis dus dubbel. Plaats de server dicht bij de telefoons of dicht bij de provider. Geef de voorkeur aan de nabijheid van de telefoons wanneer deze zich op verschillende locaties bevinden, omdat dat traject meestal over consumenteninternet loopt waar jitter het ergst is.
De codec-keuze bepaalt de bandbreedte per gesprek. Elke codec hier verstuurt elke 20 ms een pakket, wat neerkomt op 50 pakketten per seconde. Elk pakket bevat 40 bytes aan IP-, UDP- en RTP-headers boven op de audio-payload.
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 is de standaard op de meeste trunks. De payload is 64 kbps, en inclusief headers kost een lopend gesprek 80 kbps in elke richting. Opus op 24 kbps verbruikt 40 kbps, en G.729 daalt naar 24 kbps ten koste van audiokwaliteit en CPU-tijd. Deze cijfers zijn gebaseerd op header-berekeningen in plaats van metingen: payload-snelheid plus 40 bytes per pakket bij 50 pakketten per seconde. Ethernet- of VLAN-framing voegt op de fysieke verbinding nog iets extra's toe.
Transcoding kost CPU-kracht. Als uw telefoons en uw trunk beide ulaw spreken, sta dan alleen ulaw toe zodat Asterisk de audio ongewijzigd doorgeeft. Opus presteert goed op verbindingen met pakketverlies, maar voor transcoding tussen Opus en G.711 is de externe codec_opus-module vereist. Deze selecteert u in make menuselect en deze wordt standaard niet meegecompileerd.
Wat er misgaat en de melding die u ziet
De verbinding komt tot stand, maar er is niets te horen. RTP komt niet aan. Controleer of het bereik in rtp.conf overeenkomt met het bereik dat u in de firewall heeft geopend en monitor vervolgens het verkeer met sudo tcpdump -ni any udp portrange 10000-10200 terwijl u een gesprek voert. Als er helemaal geen pakketten verschijnen, worden deze geblokkeerd door uw firewall of de netwerkfirewall van uw provider.
Audio in slechts één richting. Eén kant verstuurt RTP naar een adres dat het niet kan ontvangen; dit is een adresprobleem in plaats van een poortprobleem. Als uw VPS het publieke adres direct op de interface heeft staan, is NAT-afhandeling niet nodig. Als de provider de VPS een privaat adres geeft met een een-op-een publieke koppeling, stel dan het publieke adres in op de transportlaag en vermeld uw private bereik in 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.5No matching endpoint found in het logbestand. Het verzoek kwam niet overeen met een endpoint op basis van IP-adres of gebruikersnaam. Bij een scanner is dit normaal en zal fail2ban dit afhandelen. Als dit afkomstig is van uw eigen provider, betekent dit dat de sectie identify het adres waarvan zij u bellen niet bevat.
De registratiestatus is Rejected. De provider heeft de inloggegevens in uw sectie auth geweigerd. Voer pjsip set logger on uit in de CLI, observeer één REGISTER-verzoek en het bijbehorende antwoord, en vergelijk vervolgens client_uri en username met de gegevens die u van de provider heeft ontvangen.
Helemaal niets nuttigs in het logbestand. Asterisk schrijft standaard meldingen van het niveau notice en hoger naar messages.log. Verhoog dit niveau met core set verbose 4 en pjsip set logger on terwijl u het probleem reproduceert. Schakel beide daarna weer uit, aangezien de SIP-logger elk pakket wegschrijft.
Voordat u het blootstelt
Een PBX is niet vergelijkbaar met andere applicaties die u zelf host. Een defecte webapplicatie kost u een pagina. Een defecte PBX resulteert binnen enkele uren, terwijl u slaapt, in een hoge telefoonrekening. Draai de PBX op een VPS die geen andere taken uitvoert, beperk poort 5060 tot bekende IP-adressen, geef elk toestel een willekeurig wachtwoord en stel een bestedingslimiet in op het trunk-account. De rest van de server vereist dezelfde basisbeveiliging als elke andere blootgestelde server, zoals uiteengezet in deze analyse over hoe veilig VPS-hosting werkelijk is.
FAQ
Welke poorten moet ik openen voor een zelfgehoste VoIP-server?
Poort 5060 voor SIP-signalisatie via UDP en TCP, poort 5061 als u SIP via TLS gebruikt, en een reeks UDP-poorten voor RTP-media. Het voorbeeld rtp.conf van Asterisk gebruikt 10000 tot 20000, en de standaardwaarden in de gecompileerde software zijn 5000 tot 31000. Elk gesprek verbruikt twee poorten uit deze reeks; een bereik van tweehonderd poorten ondersteunt dus honderd gelijktijdige gesprekken. Open het RTP-bereik als UDP en beperk poort 5060 tot de adressen van uw provider en uw eigen netwerken in plaats van deze voor iedereen open te stellen.
Moet ik Asterisk los installeren of FreePBX gebruiken?
Installeer kale Asterisk als u een klein aanvalsoppervlak wilt, configuratiebestanden in git wilt beheren en bereid bent om de dialplan-logica zelf te schrijven. Installeer FreePBX als u een GUI wilt voor extensies, voicemail en wachtrijen. Sinds augustus 2026 vereist het installatieprogramma van FreePBX 17 een schone Debian 12-machine en installeert het Asterisk, een webserver, een databaseserver en PHP; wijs hier dus een eigen VPS aan toe. FreePBX genereert de configuratiebestanden die het beheert opnieuw, dus handmatige wijzigingen horen thuis in de bijbehorende _custom-bestanden.
Waarom is er geen audio nadat de verbinding tot stand is gekomen?
De signalisatie werkte, maar de media niet. SIP zette het gesprek op via poort 5060, terwijl de audio een afzonderlijke UDP-stroom is naar een poort in het RTP-bereik die door iets wordt tegengehouden. Controleer of het bereik in rtp.conf overeenkomt met het bereik dat openstaat in uw firewall, en controleer zowel de netwerkfirewall van uw provider als die op de server zelf. Voer sudo tcpdump -ni any udp portrange 10000-10200 uit tijdens een gesprek: als er geen pakketten worden getoond, worden ze geblokkeerd voordat ze aankomen.
Hoe stop ik SIP-brute-force-aanvallen en toll fraud?
Geef elke extensie een lang, willekeurig wachtwoord; gebruik nooit een wachtwoord dat gelijk is aan het extensienummer. Houd de context die door uw trunk wordt gebruikt gescheiden van elke context die naar buiten kan bellen, zodat een inkomend gesprek niet via uw account naar buiten kan bellen. Beperk poort 5060 tot de adressen van uw provider. Schakel de asterisk-jail in fail2ban in, die /var/log/asterisk/messages uitleest en de adressen blokkeert die No matching endpoint found-fouten veroorzaken. Stel daarnaast een bestedingslimiet in en blokkeer ongebruikte internationale bestemmingen bij uw provider, aangezien dat de enige controle is die het verlies beperkt als de rest faalt.
Heeft een VPS in een verre regio invloed op de gesprekskwaliteit?
Ja, omdat de audio twee trajecten aflegt: telefoon naar VPS, en vervolgens VPS naar de trunk-provider. ITU-T G.114 adviseert een eenzijdige vertraging van minder dan 150 ms, en een slecht geplaatste VPS kan het grootste deel van dat budget al verbruiken door de afstand. Kies een regio dicht bij de telefoons, aangezien dat traject meestal over consumenteninternet loopt waar jitter het ergst is. De keuze voor een codec lost vertraging niet op, het verandert alleen de bandbreedte; G.729 bespaart dus bytes, maar redt geen verbinding met een vertraging van 200 ms.