電話システムが深夜に落ちた夜
火曜日の夜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ドル固定だった。しかもその夜、大口顧客との商談の前夜に落ちた。自己ホスト型に切り替えてから、そんなことは一度もない。

