LinuxでFreePBXとAsteriskによる自己ホスト型VoIP PBX構築:ゼロからSIPトランク接続まで

Networking tutorial - IT technology blog
Networking tutorial - IT technology blog

電話システムが深夜に落ちた夜

火曜日の夜11時47分、電話が鳴った。CEOからだ。「会社の電話回線が全部つながらない。明日の朝9時に大口顧客との商談があるのに」。ホステッドPBXのダッシュボードを確認すると、見慣れた悪夢が広がっていた。プロバイダのサービスが完全にダウンしており、復旧時刻の見通しもなく、サポートチケットは3日分溜まっている。

その週末、月12ドルのVPS上に完全に動作する自己ホスト型PBXを構築した。格安プロバイダのSIPトランク、チーム全員分の内線番号、そして理にかなった着信ルーティングを備えたシステムだ。その構成は14ヶ月間、本番稼働し続けている。ダウンタイムはVPSの計画メンテナンスが2回あっただけだ。

以下に、まったく同じ構成を再現する手順を詳しく解説する。

実際に何を構築するのか

コマンドを触る前に、全体像をしっかり把握しておこう。

Asteriskはオープンソースのテレフォニーエンジンだ。通話処理、音声ブリッジ、プロトコル変換を担当する。電話システムにおけるカーネルのような存在と考えればよい。

FreePBXはAsteriskをラップするWebインターフェースだ。FreePBXがなければ、Asteriskの設定は.confファイルを手動で編集し、構文が正しいことを祈るしかない。FreePBXはそれをデータベースバックエンドの合理的なGUIに変換してくれる。

通話の流れはこうなる:

  • SIPトランク:外部世界への接続。VoIPプロバイダが実際の電話番号を提供し、インターネット経由でサーバーへ着信を転送する
  • 内線番号:ネットワーク上のソフトフォンやIP電話機に割り当てられた内部番号(101、102など)
  • ダイヤルプラン:着信をどこに転送するかを決めるルール。トランクからの着信を内線101、呼び出しグループ、またはIVRメニューに振り分ける

1 vCPU / 2 GB のVPSなら、G.711コーデックで20〜30同時通話を余裕でこなせる。ほとんどの小規模チームには十分な性能だ。

事前準備

  • Linuxサーバー — Rocky Linux 9またはUbuntu 22.04 LTS、最低1 vCPUと1 GB RAM
  • パブリックIPアドレス(LAN内のみで使う場合は固定プライベートIPでも可)
  • SIPトランクアカウント — このガイドではVoIP.msを使用(従量課金制、契約不要、米国通話は約$0.009/分)
  • UDP 5060(SIP)とUDP 10000〜20000(RTP音声)を開放するファイアウォールの権限

FreePBXのインストール

まず必要なファイアウォールポートを開放する。Asteriskは起動と同時にこれらのポートを必要とするため、インストーラを実行する前に済ませておくこと。

Rocky Linux 9の場合:

firewall-cmd --permanent --add-port=80/tcp
firewall-cmd --permanent --add-port=443/tcp
firewall-cmd --permanent --add-port=5060/udp
firewall-cmd --permanent --add-port=5061/tcp
firewall-cmd --permanent --add-port=10000-20000/udp
firewall-cmd --reload

Ubuntu 22.04の場合は、まずコアの依存関係をインストールする:

apt update && apt install -y \
  git curl wget \
  php8.1 php8.1-curl php8.1-xml php8.1-mysql php8.1-mbstring \
  apache2 mariadb-server asterisk asterisk-config

systemctl enable --now asterisk mariadb apache2

次にFreePBXインストーラを取得して実行する:

cd /usr/src
wget http://mirror.freepbx.org/modules/_cache/freepbx-17.0-latest.tgz
tar xfz freepbx-17.0-latest.tgz
cd freepbx
./install -n

インストールには10〜15分かかる。完了したらブラウザでhttp://サーバーのIPアドレスを開き、セットアップウィザードを進める。まず最初に、強力な管理者パスワードを設定すること。

すぐにセキュリティを固める

SIPスキャナーはサーバーが公開されてから数時間以内に見つけてくる。FreePBXのGUIでAdmin → System Admin → Intrusion Detectionに移動し、fail2ban連携を有効にする。登録試行が繰り返し失敗したIPを自動的にブロックするため、自動化された不正通話攻撃の大半を未然に防ぐことができる。

最初のSIPトランクを設定する

Connectivity → Trunks → Add Trunk → Add SIP (chan_pjsip) Trunkに移動する。

VoIP.msの設定はこのようになる:

Trunk Name: voipms-main

=== 基本設定 ===
Username: VoIP.msのユーザー名
Secret: VoIP.msのパスワード
SIP Server: denver.voip.ms    # 最寄りのPOPを選択
SIP Port: 5060

=== 詳細設定(pjsip)===
Authentication: Outbound
Registration: Send
Match Inbound Auth: Username

保存後、Admin → Asterisk Logfilesを開いて以下のメッセージを確認する:

Registered SIP 'voipms-main' at denver.voip.ms

このメッセージが表示されればトランクは正常に接続されている。Authentication failedが表示される場合は2つを確認する:認証情報が正しいか、そしてVoIP.msアカウントがユーザー名/パスワード認証を使っているか。もう1つの選択肢としてIPベース認証があり、アカウントの「Authentication Type」設定で確認できる。IPベース認証が有効な場合、ユーザー名/パスワードは機能しない。

内線番号を追加する

Applications → Extensions → Add Extension → Add New PJSIP Extensionを開く。

Extension: 101
Display Name: 山田太郎
Secret: 強力なランダムパスワードを使用すること

各ユーザーに対して同様に繰り返す。次にソフトフォンを設定する。Zoiper、MicroSIP(Windows)は無料で使える。LinuxではLinphoneが動作する。以下の設定を入力する:

Domain/Server: サーバーのIPアドレス
Username: 101
Password: 設定したパスワード
Transport: UDP
Port: 5060

登録が完了すると、内線同士は番号を直接ダイヤルして通話できる。トランクを使わず、分単位の料金も発生しない。通話はAsterisk内部で完結する。

着信・発信のルーティング設定

着信ルート

着信ルートはConnectivity → Inbound Routes → Add Incoming Routeから設定する:

Description: メイン回線
DID Number: +15551234567    # VoIP.msから取得した電話番号
Destination: Extensions → 101

時間外対応が必要な場合は、Applications → Time Conditions時間条件を追加し、着信をそこ経由でルーティングする。営業時間中は内線101に転送し、夜間はボイスメールに落とすといった設定が可能だ。

発信ルート

発信にはConnectivity → Outbound Routes → Add Outbound Routeを開く:

Route Name: external-calls
Trunk Sequence: voipms-main

Dial Patterns:
  Match Pattern: NXXNXXXXXX    # 米国の10桁番号
  Match Pattern: 1NXXNXXXXXX  # 国番号付き11桁番号

変更を適用し、内線101から外部番号に発信して正常につながることを確認する。

片方向音声の問題をデバッグする(深夜2時の定番トラブル)

片方向音声は自己ホスト型VoIPで最も頻繁に発生するトラブルだ。相手の声は聞こえるが自分の声が届かない、あるいはその逆。ほぼ確実にNATが原因だ。

# Asterisk CLIに接続してライブ通話を監視する
asterisk -rvvv

# 通話中にRTPストリームの行を確認する
# 送信と受信の両方が表示されるはずだ:
# [VERBOSE] RTP Packet send: ...
# [VERBOSE] RTP Packet received: ...

解決策はAsteriskにパブリックIPを教えることだ。FreePBXでSettings → Asterisk SIP Settings → General SIP Settingsに移動する:

External IP: サーバーのパブリックIPアドレス
Local Networks: 192.168.1.0/24   # LANのサブネット

この設定がないと、サーバーはSDPオファーにプライベートIPを通知してしまう。相手側はそのプライベートアドレスに音声を送ろうとするが、当然届かない。

トランク登録の問題はCLIから直接確認できる:

pjsip show registrations
# 以下のように表示されるはずだ:
# voipms-main    Registered    denver.voip.ms:5060

次に追加すべき機能

基本システムで最低限の機能は揃った。本番運用と呼べるレベルにするために、以下の4つを追加しておきたい:

  • 通話録音:各内線の設定から内線ごとに有効化する。録音ファイルは/var/spool/asterisk/monitor/に保存され、FreePBXの録音モジュールから直接再生できる
  • SIP TLS + SRTP:電話機とサーバー間のシグナリング(ポート5061)と音声を暗号化する。オフィス外から接続する内線には特に重要だ
  • 定期バックアップ:忘れる前にAdmin → Backup & Restoreから設定しておく。バックアップなしでFreePBXをゼロから再構築するのは半日がかりの苦行だ
  • モジュールの更新Admin → Module Admin → Check Onlineから月1回確認する。インターネットに公開されたSIPサーバーは常に攻撃対象だ。セキュリティパッチの適用を怠らないこと

総運用コスト:2 vCPU / 2 GB VPSで月約12ドル、加えてトランクの従量課金。月2,000分利用するチームがVoIP.msを使えば合計約18ドル程度になる。これを置き換えた以前のホステッドサービスは月180ドル固定だった。しかもその夜、大口顧客との商談の前夜に落ちた。自己ホスト型に切り替えてから、そんなことは一度もない。

Share: