Construction d'un système VoIP avec Twilio, 3CX et Python

March 18, 2020
Rédigé par
Scott Sturdivant
Contributeur
Les opinions exprimées par les contributeurs de Twilio sont les leurs

Construction d'un système VoIP avec Twilio, 3CX et Python

Mettre en marche votre propre ligne téléphonique VoIP n'a jamais été aussi simple avec Twilio et 3CX.  Dans ce tutoriel, nous verrons comment intégrer les deux afin de passer des appels téléphoniques à bas prix.

Dépendances du projet

Pour mettre en œuvre ce projet, nous aurons recours à un certain nombre de produits, décrits ci-dessous.

Elastic SIP Trunking de Twilio

Un trunk SIP est un composant essentiel qui connecte votre système téléphonique VoIP au réseau téléphonique commuté public (RTCP).  SIP Trunking de Twilio offre une solution abordable, flexible et robuste capable d'alimenter tant les réseaux téléphoniques d'entreprise que les lignes domestiques uniques.

diagramme de trunk sip
 

Vous pouvez consulter de plus amples informations sur les trunks SIP ici.

Vous n'avez pas encore de compte Twilio ?  Créez gratuitement votre compte dès maintenant. En utilisant ce lien pour vous inscrire, vous recevrez un crédit de 10 $ à dépenser lors de votre mise à niveau vers un compte payant.

Numéro de téléphone Twilio

Pour passer ou recevoir des appels téléphoniques, nous allons avoir besoin d'un numéro de téléphone. Twilio permet d'en obtenir un facilement grâce à ses offres de numéro de téléphone programmableInscrivez-vous pour obtenir un numéro ou envisagez d'utiliser votre numéro existant en créant une demande de portabilité.  À des fins de test, le numéro de téléphone programmable est une méthode rapide permettant de valider votre configuration avant de demander la portabilité de votre propre numéro dans l'écosystème Twilio.

IP PBX 3CX

Un IP Private Branch Exchange (PBX) est un système qui connecte des lignes téléphoniques internes à des lignes externes.  Lorsque vous passez un appel et que vous êtes routé vers le poste d'une personne spécifique, cet appel passe par un PBX. Un IP PBX connecte les téléphones VoIP à un trunk SIP.

Deux des plus grands fournisseurs d'IP PBX gratuits sont FreePBX et 3CX. Dans le cadre de ce tutoriel, nous utiliserons 3CX, ainsi qu'une licence gratuite. Pour des niveaux de performances plus élevés, vous pouvez également acheter une licence répondant à vos besoins.

L'installation de 3CX dépassant le cadre de ce tutoriel, nous vous renvoyons plutôt vers l'excellente documentation 3CX, qui peut vous aider à installer 3CX pour Windows ou Linux, que ce soit sur site ou dans le cloud. Une fois l'installation terminée et le test du pare-feu réussi, vous pouvez y intégrer le trunk SIP de Twilio.

Téléphones

Si vous avez un téléphone VoIP à portée de main, vérifiez qu'il est compatible avec 3CX.  Si ce n'est pas le cas, ne vous inquiétez pas. Vous pouvez utiliser les applications Android et iOS.  Une fois votre téléphone ou application VoIP configuré, vous pouvez passer et recevoir des appels sur ce téléphone via 3CX et le trunk SIP Twilio.

Python

Nous utiliserons Python et la bibliothèque Twilio afin de nous assurer que notre liste de contrôle d'accès IP reste à jour.  Nous exécuterons un cronjob périodique afin de vérifier notre adresse IP publique. Si jamais elle change, nous la mettrons à jour dans Twilio. 

Configuration de Twilio

Nous pouvons commencer notre exercice en configurant d'abord la partie Twilio. Le trunk SIP de Twilio servira de pont entre Internet et le RTCP.

Trunk SIP

Commençons par nous rendre sur la page Elastic SIP Trunking :

SIP Trunking élastique en option

Ensuite, sélectionnez Trunks, puis « Create New SIP Trunk » (Créer un nouveau trunk SIP) :

tableau de bord de trunks sip élastiques

Donnez-lui un nom convivial, puis appuyez sur « Create » (Créer) :

création d'un nouveau trunk sip

Terminaison de trunk

Une fois créés, nous pouvons laisser tous les paramètres de la page General (Général) inchangés et passer à la section Termination (Terminaison).  Lorsque 3CX passe un appel, c'est là qu'il envoie les informations sur l'appel à Twilio.

diagramme trunk sip et twilio

Continuez en configurant un URI unique :

configuration de l'uri unique du trunk sip

Cette valeur complète (dans notre cas « twilio-3cx.pstn.twilio.com », mais la vôtre sera différente) sera finalement ajoutée à la configuration de trunk 3CX.

Passons maintenant à la section Authentication (Authentification).  Commencez par créer une liste de contrôle d'accès IP qui possède l'adresse IP publique de votre installation 3CX.  Ces informations figurent dans le tableau de bord 3CX :

nom de domaine complet et adresse ip 3cx

Appliquez les mêmes informations dans la boîte de dialogue de création de liste de contrôle d'accès :

nouvelle liste de contrôle d'accès

Ensuite, dans la liste des informations d'identification, créez un nom d'utilisateur et son mot de passe associé.  Ces informations figureront également dans la configuration du trunk 3CX :

nouvelle liste d'informations d'identification

Appuyez sur Create (Créer) et passez à la page Origination (Origine).

Origine du trunk

Dans la section Origination (Origine) de la configuration, ajoutez un nouvel URI d'origine, en spécifiant votre nom de domaine complet 3CX (disponible dans le tableau de bord 3CX) précédé du préfixe « sip: » :

ajout de l'url d'origine

Numéros de trunk

Enfin, dans la section Numbers (Numéros), nous devons alimenter notre trunk SIP à l'aide d'un numéro de téléphone :

numéros de téléphone trunk sip

Recherchez un numéro qui répond à vos critères, achetez-le et il sera ajouté à votre trunk.  Ainsi s'achève la configuration de Twilio !

Configuration de 3CX

Maintenant que nous avons créé un trunk SIP, le moment est venu de l'ajouter à 3CX !

Trunk SIP

Dans le tableau de bord 3CX, accédez à « SIP Trunks » (Trunks SIP), puis à « Add SIP Trunk » (Ajouter un trunk SIP).

Sélectionnez pour pays « Generic » (Générique) et pour fournisseur de trunk SIP, « Generic » (Générique).  Le « Main Trunk No » (Numéro de trunk principal) est le numéro de téléphone complet E.164 que vous avez ajouté au trunk :

configuration du trunk sip 3cx

Après avoir appuyé sur OK, vous pouvez donner au trunk un nom tel que « Twilio ».  Nous devons par ailleurs ajouter le nom de domaine complet qui correspond à l'URI SIP de terminaison de notre trunk :

configuration de l'uri trunk sip 3cx twilio

Il s'agit ensuite de configurer la section Authentication (Authentification).  REMARQUE : nous sélectionnons l'option « Do not require - IP Based » (N'a pas besoin d'être basé sur IP) dans la liste déroulante « Type of Authentication » (Type d'authentification), mais saisissons tout de même l'ID et le mot de passe que nous avions définis dans la liste des informations d'identification de Twilio.  Il semble que Twilio ne prenne pas en charge le processus d'enregistrement de 3CX, mais si nous négligeons les informations d'identification, les appels seront rejetés avec une erreur 403 Accès refusé.

configuration de l'authentification 3cx

Passez maintenant à l'onglet Caller ID (ID de l'appelant) et définissez votre numéro comme Default Caller ID (ID d'appelant par défaut), à nouveau au format E.164 :

configuration de l'id appelé 3cx

Enregistrez la configuration du trunk SIP avant de continuer.

Règles de trafic entrant

Sélectionnez Inbound Rules (Règles de trafic entrant) et créez une nouvelle règle.  Nous configurons ici 3CX pour qu'il sache quoi faire lorsqu'il reçoit un nouvel appel. Dans ce cas précis, je l'achemine simplement vers mon poste, qui doit être configuré en tant que téléphone VoIP avec 3CX :

ajout d'une règle de trafic entrant 3cx

Règles de trafic sortant

Pour finir, nous définissons les règles de trafic sortant. Étant établi aux États-Unis, je voudrais qu'il suffise de composer l'indicatif régional et le numéro pour que l'appel soit passé.  Pour convertir cela en numéro E.164 valide, je dois donc ajouter à un numéro à dix chiffres le préfixe « +1 ».  Dans cette optique, créons la règle suivante, en veillant à ce que les numéros aient une longueur de 10 chiffres, en acheminant l'appel vers notre trunk Twilio, et en y ajoutant le préfixe +1 :

ajout d'une règle de trafic sortant 3cx

Selon votre situation géographique et la manière dont vous préférez passer les appels, ces règles de trafic sortant peuvent être largement personnalisées selon vos besoins. 3CX présente d'ailleurs quelques exemples de règles au bas de la page de documentation Twilio.

Si les appels sortants échouent et que vous n'êtes pas sûr de savoir pourquoi, vérifiez à la fois les journaux d'activité 3CX et les journaux Twilio associés au trunk SIP. Il arrive souvent que les échecs soient dus à un format incorrect du numéro composé.

Téléphones

Si vous n'avez pas configuré votre téléphone, faites-le maintenant.  Si vous n'avez pas de téléphone VoIP, l'application 3CX disponible à la fois pour Android et pour iOS peut être configurée rapidement en scannant un code QR associé à un poste.

Mise à jour de la liste de contrôle d'accès IP

À ce stade, vous devriez pouvoir passer et recevoir des appels téléphoniques.  Si toutefois vous utilisez une adresse IP dynamique comme moi, vous craignez probablement que la connexion ne coupe lorsque votre adresse IP changera. Pour dissiper ces craintes, nous allons créer une application simple mettant à jour notre liste de contrôle d'accès IP lorsqu'un changement est détecté.

Python

Pour séparer nos bibliothèques des bibliothèques système, nous suivons les bonnes pratiques Python et créons un environnement virtuel, puis l'activons :

$ python -m venv venv
$ source venv/bin/activate  # for Unix and Mac OS
$ venv\Scripts\activate    # for Windows

Nous utilisons la bibliothèque Python Twilio, qui permet une installation simple comme indiqué ci-dessous :

(venv) $ pip install twilio

L'application elle-même est relativement courte. Appelons-la update_acl.py :

#!/path/to/your/venv/bin/python
import os
import requests
from twilio.rest import Client

ACCOUNT_SID = os.getenv('TWILIO_ACCOUNT_SID')
ACCOUNT_TOKEN = os.getenv('TWILIO_ACCOUNT_TOKEN')
ACL_NAME = os.getenv('TWILIO_ACL_NAME')


def get_current_ip():
    return requests.get('http://ifconfig.io/ip').text.strip()


def store_ip(ip):
    with open('/tmp/ip.txt', 'w+') as f:
        f.write(ip)


def get_stored_ip():
    try:
        return open('/tmp/ip.txt', 'r').read()
    except OSError:
        return None


def ip_needs_update():
    current_ip = get_current_ip()
    old_ip = get_stored_ip()

    if old_ip != current_ip:
        store_ip(current_ip)
        return True


def find_acl(client, name=ACL_NAME):
    for auth in client.sip.ip_access_control_lists.stream():
        if auth.friendly_name == name:
            return auth


def update_ip(auth):
    new_ip = get_stored_ip()
    ip = auth.ip_addresses.list()[0]
    ip.update(ip_address=new_ip)


def main():
    # Has the IP changed? If not, we do not need to do anything.
    if not ip_needs_update():
        return

    client = Client(ACCOUNT_SID, ACCOUNT_TOKEN)
    auth_acl = find_acl(client)
    update_ip(auth_acl)


if __name__ == '__main__':
    main()

Au début de l'application, nous voyons d'abord que le chemin shebang pointe vers l'interpréteur Python associé à l'environnement virtuel. Il doit être mis à jour pour refléter le chemin de votre environnement virtuel.

Ensuite, trois variables d'environnement sont nécessaires.  Le SID de compte Twilio et le token d'autorisation sont tous deux indiqués dans votre console Twilio.  Ils sont nécessaires pour que le client REST Twilio s'authentifie correctement.  Le nom de la liste de contrôle d'accès est requis car c'est ce qui va nous permettre de rechercher la liste de contrôle d'accès IP devant être modifiée.  Il s'agit du « nom convivial » que vous avez donné à la liste de contrôle d'accès IP. Si vous ne vous en souvenez pas, vous pouvez le trouver en vous rendant dans « Elastic SIP Trunking » -> « Authentication » -> « IP Access Control List » (Elastic SIP Trunking -> Authentification -> Liste de contrôle d'accès IP).

Appeler ce script manuellement depuis la ligne de commande comme suit :

$ ./update_acl.py

Le script Python compare son adresse IP externe actuelle à la dernière valeur enregistrée (stockée dans un fichier nommé ip.txt) et, s'il détecte une modification, il recherche la liste de contrôle d'accès IP associée à votre trunk SIP et met à jour son adresse IP.

crontab

Maintenant que nous avons la possibilité de mettre à jour la liste de contrôle d'accès IP de Twilio, tout ce qui reste à faire, c'est de la planifier périodiquement.  Si vous utilisez un système Unix, crontab est idéal pour réaliser cette tâche.  Créons un cronjob qui s'exécutera toutes les quinze minutes. Pour cela, saisissez crontab -e afin de commencer à éditer le crontab.  Ajoutez la ligne suivante :

*/15 * * * * TWILIO_ACCOUNT_SID=<your_sid> TWILIO_ACCOUNT_TOKEN=<your_token> TWILIO_ACL_NAME=<your_acl_name> /path/to/your/code/update_acl.py

Veillez à renseigner les variables d'environnement selon vos valeurs réelles. De plus, vérifiez que le chemin d'accès vers l'emplacement où vous avez enregistré update_acl.py est exact.

Maintenant, toutes les 15 minutes, le script s'exécutera et comparera votre adresse IP externe actuelle avec votre dernière valeur enregistrée.  Si elle a changé, il mettra à jour la liste de contrôle d'accès IP de Twilio pour refléter cette nouvelle adresse IP. Le résultat final est que votre service téléphonique ne sera pas interrompu si votre adresse IP change !

Conclusion

Twilio et 3CX sont tous deux incroyablement puissants, et c'est formidable de pouvoir les associer !  Avec un peu de Python et la bibliothèque Twilio Python Helper, nous sommes en mesure d'apporter la petite touche qui permet de les réunir en une expérience homogène.

J'adorerais voir ce que vous avez construit !

GitHub