SSD Nodes Learn 🎉 VPS $5.50/月〜
ガイド Matt Connor著者 Matt Connor

AsteriskとFreePBXでVoIPサーバーを自前構築する方法

VPSでAsteriskやFreePBXを運用する手順を解説します。SIPトランク、RTPポート範囲、スキャナーを防ぐファイアウォール設定、トール詐欺の始まりまで確認できます。

セルフホスト型 VoIP サーバーとは

セルフホスト型 VoIP サーバーは、管理下にある VPS で稼働する SIP サーバーです。ホスティング型の電話サービスではなく、自分のサーバーが通話を中継します。VoIP(voice over IP)は、音声を UDP パケットとして伝送します。SIP(session initiation protocol)は、通話の開始と終了を制御するシグナリングです。音声は SIP 経由では伝送されません。この点が、以下で説明する問題の大半を引き起こします。

動作するシステムは、4 つの要素で構成されます。

  • PBX(private branch exchange)ソフトウェア。通常は Asterisk を使用します。内線番号とダイヤルプランを管理します。
  • エンドポイント。デスクフォンまたはソフトフォンです。ユーザー名と Secret を使用して PBX に登録します。
  • SIP トランク。通信事業者が提供する有料アカウントです。公衆電話網への接続と、実際の電話番号の貸し出しを提供します。
  • メディア経路。音声を運ぶ RTP(real-time transport protocol)フローです。RTP は専用の UDP ポートを使用します。

PBX をセルフホストしても、電話番号までセルフホストすることにはなりません。電話番号は通信事業者から取得し、番号ごとおよび通話時間ごとに料金を支払います。自分で管理するのは、通話のルーティング、ボイスメール、録音、内線番号の一覧です。また、金銭目的の攻撃対象になるサービスのセキュリティも自分で管理する必要があります。

自己ホスト型 VoIP サーバーには、どのポートが必要ですか?

SIP シグナリングでは、UDP と TCP にポート 5060 を使用し、SIP over TLS(transport layer security)にはポート 5061 を使用します。これらのポートで処理するのは、通話の確立だけです。各通話の音声は別の UDP フローとして、RTP の範囲から選ばれたポートに送信されます。Asterisk には rtp.conf のサンプルが付属しており、rtpstart=10000rtpend=20000 を設定します。コンパイル時のデフォルト値は 5000 と 31000 です。各通話では、この範囲から 2 つのポートを使用します。1 つは RTP 用、もう 1 つは RTCP(RTP control protocol)用です。

この分離が、最初の構築で最もよく問題になる部分です。通話は接続され、両方の電話機には応答済みと表示されますが、ファイアウォールが 5060 を許可し、RTP パケットをすべて破棄しているため、どちらからも音声が聞こえません。シグナリングとメディアは別々のフローなので、個別のファイアウォールルールが必要です。この違いが初めてであれば、何かを開放する前に Linux でポートと待ち受けソケットが機能する仕組み を読むとよいでしょう。

開放する前に、ポート範囲を狭めてください。20000 ポートは、小規模なシステムには過剰です。1 通話につき 2 ポートを使用するため、範囲を 200 ポートにすれば同時に 100 通話を処理できます。

[general]
rtpstart=10000
rtpend=10200

sudo asterisk -rx "core reload" で適用します。

Asterisk と FreePBX のどちらをインストールすべきですか?

Asterisk はエンジンです。/etc/asterisk にあるテキストファイルを使って設定し、ダイヤルプランを自分で記述します。FreePBX は PHP と JavaScript で作られた Web インターフェースです。Asterisk の上で動作し、設定ファイルを生成し、ボイスメールやコールキュー用のモジュールを追加します。

VPS で重要なのは、そのマシンを誰が管理するかです。2026 年 8 月時点で、公式の FreePBX 17 インストーラーは、標準状態の Debian 12 システムを前提としています。Asterisk、Web サーバー、データベースサーバー、PHP をインストールします。すでに別のサービスが動作しているサーバーで実行すると、問題が発生します。FreePBX には専用の 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.sh

インストールログは /var/log/pbx/freepbx17-install.log に保存されます。スクリプトが早い段階で停止した場合、最初に確認する場所です。

FreePBX は、自身が生成した設定ファイルを管理します。FreePBX 環境で pjsip.conf を手動編集しても、次に GUI がそのファイルを書き込んだ時点で変更が消えます。FreePBX は、名前に _custom を含む別のファイルを手書き設定用に読み込みます。これらのファイルは変更しません。

実際のトレードオフは明確です。FreePBX では GUI を使用できますが、電話システムのログインページをパブリックインターネットに公開することになります。Asterisk 単体には Web インターフェースがなく、すべての設定がファイル内の文書化されたディレクティブとして確認でき、git で管理できます。FreePBX をインストールする場合は、Web ポートへのアクセスを自分のアドレスに制限するか、VPN 経由で接続してください。PBX の管理 GUI は、金銭に直結する経路を持つ攻撃対象です。

バージョン情報(2026 年 8 月時点):Asterisk 22 は現在の長期サポートリリースです。2024 年 10 月に公開され、2028 年 10 月までセキュリティ修正が提供されます。Asterisk 23 は標準リリースです。Ubuntu 24.04 の universe リポジトリには Asterisk 20.6.0 が含まれています。

Ubuntu 24.04 に Asterisk をインストールする

ディストリビューションのパッケージを使う方法が最も簡単です。Ubuntu によるパッチが適用され、systemd で自動的に起動します。

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

ソースからビルドすると、代わりに現在の long term support リリースを利用できます。

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 はディストリビューションに必要なビルド依存関係を取得し、install_prereq test は実行せずに実行予定のコマンドを表示します。make menuselect はモジュール選択画面を開きます。ここで Codec Translators の下にある codec_opus を有効にします。make samples は新規インストール時だけ実行してください。サンプル設定を /etc/asterisk に書き込むためです。make config は init スクリプトを /etc/init.d/asterisk にインストールします。systemd は SysV 互換レイヤーを通じてこのスクリプトを実行するため、その後は sudo systemctl enable --now asterisk が機能します。

どちらの方法を選んだ場合も、sudo asterisk -rvvv で実行中の daemon に接続し、CLI を開けます。そこで core show version を実行すると、実際にインストールされた内容が表示されます。

SIP トランクと 1 つの内線を設定する

現在の Asterisk では、PJSIP が SIP チャネルドライバーです。設定は /etc/asterisk/pjsip.conf にあり、名前で相互参照する小さな型付きセクションから構成されます。異なる種類のセクションでも同じ名前を付けられるため、以下の各ブロックはすべて 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

registration オブジェクトは、プロバイダーに着信先を通知する REGISTER を送信します。プロバイダーから着信した通話を送信元アドレスでこのエンドポイントに照合するのが identify オブジェクトです。通常、プロバイダーはここに登録する複数のアドレスを公開します。発信登録とエンドポイントを別々のオブジェクトにするのは意図的な設計です。一方はプロバイダーに自分の所在を通知し、もう一方は着信した通話の処理を決定します。

卓上電話には、さらに 3 つのオブジェクトが必要です。

[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 によって、Asterisk はメディア経路に残ります。これを省略すると、Asterisk は 2 つのエンドポイントに RTP を直接送信させようとします。電話機が自宅ルーターの NAT(ネットワークアドレス変換)配下にある場合、これは失敗します。Secret を内線番号と同じにしてはいけません。上流のサンプルでは、例を読みやすくするため、内線 6001 に password=6001 を使用していますが、スキャナーは最初にこのパターンを試します。

/etc/asterisk/extensions.conf のダイヤルプランによって、各コンテキストで許可される操作が決まります。

[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()

この 2 つのコンテキストはセキュリティ境界です。from-trunk はプロバイダーからの着信を処理し、内線 6001 のみを呼び出せます。_9X. パターンには到達できないため、外部からの発信者がトランク経由で折り返し発信することはできません。コンテキストを統合すると、典型的な有料通話詐欺の経路ができます。第三者があなたの番号に電話をかけ、ダイヤルプランであなたのアカウントから発信し、その料金をあなたが負担することになります。

設定を適用して確認します。

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

pjsip show registrationsmytrunk が表示され、ステータスが Registered になっていることを確認します。Rejected は、プロバイダーが認証情報を拒否したことを示します。Unregistered は REGISTER に応答がないことを示すため、次にファイアウォールを確認してください。

SIP と RTP のファイアウォールルール

シグナリングとメディアは異なるリスクを伴うため、別々に扱う必要があります。5060 は、プロバイダーが実際に使用するアドレスと、電話機が接続されているネットワークに限定してください。

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

RTP の範囲は、シグナリングほど狭くできません。メディアは、シグナリングとは異なるアドレスから届くことが多いためです。プロバイダーにメディア用サブネットを確認し、公開されている場合はそのサブネットに制限してください。範囲は、最も通信量の多い時間帯に必要な大きさだけにしてください。デフォルトポリシー、ルールの順序、その他の ufw の仕組みについては、VPS 向け ufw ファイアウォールの基本ガイドで説明しています。

IPv6 も確認してください。/etc/default/ufwIPV6=no が設定されている場合、ufw は IPv6 をまったくフィルタリングしません。そのため、:: にバインドされたデーモンには、上記のルールが一切適用されないまま IPv6 経由で到達できます。ufw で IPv6 のポートを開くでは、2 つのアドレスファミリーの違いを説明しています。多くのプロバイダーは、コントロールパネルに別のネットワークファイアウォールも提供しています。これはパケットが VPS に到達する前に適用されるため、ポートは両方で開く必要があります。

SIP のブルートフォース攻撃と料金詐欺は、任意で対策する問題ではありません

5060 番ポートをパブリックアドレスで待ち受けると、スキャンが始まります。攻撃は一定のパターンで行われます。多数の送信元アドレスから REGISTER と INVITE リクエストを送り、一般的な内線番号と一般的な Secret を試します。Asterisk は各失敗をログに記録します。ログは次の形式です。

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

この問題に本格的に対処する必要がある理由は、金銭的な被害につながるためです。窃取された内線は、高額な国際電話の発信に使われます。攻撃者に分け前が支払われるプレミアムレート番号が使われることもあります。通話にはあなたの認証情報が使われるため、料金を負担するのはあなたです。攻撃はマシンの速度で実行され、通常は夜間にも継続します。

次の6つの対策は、任意の強化策ではなく必須です。

  • Secret に内線番号そのものや短い単語を設定した内線は作成しないでください。openssl rand -base64 24 で生成し、貼り付けてください。
  • 匿名の着信を無効のままにしてください。PJSIP はデフォルトで識別できない着信を拒否します。anonymous という名前の endpoint を作成した場合に限り、これを受け入れます。作成しないでください。
  • 前述のとおり、trunk の context は発信可能な context から分離してください。
  • ufw とプロバイダーのネットワークファイアウォールの両方で、送信元アドレスによるシグナリングの制限を設定してください。
  • SIP trunk プロバイダーで利用上限額を設定し、利用しない国際発信先を無効にしてください。他の対策が失敗した場合に損失を制限できるのは、この対策だけです。
  • Asterisk のログに対して fail2ban を実行してください。

Asterisk は、1つのアドレスから一致しないリクエストが繰り返し送信された場合に、セキュリティイベントを生成することもできます。pjsip.conf[global] セクションでは、unidentified_request_countunidentified_request_period を設定します。デフォルト値はそれぞれ 5 と 5 秒です。これらを組み合わせると、1つのアドレスから5秒以内に一致しないリクエストが5件送信された場合にセキュリティイベントが生成され、fail2ban が処理できます。

スキャナーをfail2banで遮断する

fail2banには、すでに作成済みのasterisk jailが含まれています。ポート5060と5061を対象とし、/var/log/asterisk/messagesを読み込み、デフォルトではmaxretry = 10を使用します。/etc/fail2ban/jail.localで有効にするまで、このjailは無効です。

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

正常な結果には、jailのログファイルと、現在禁止されているアドレス数が表示されます。5060番ポートを公開すると、その数は1日以内に0ではなくなります。付属のフィルターは、上記のNo matching endpoint found通知に一致します。また、Asteriskの構造化されたSecurityEvent行にも一致します。これらのイベントは、/etc/asterisk/logger.confでコメントアウトされている別のログチャネルに出力されます。これらも対象にする場合は、そこで有効にし、ファイルをjailのlogpathに追加します。

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

sudo asterisk -rx "logger reload"でロガーを再読み込みします。このフィルターにはasterisk.service用のjournalmatchも含まれているため、ログファイルを保持したくない場合はjournalバックエンドを使用できます。インストール、jail.localの構成、誤って自分を締め出したアドレスの禁止解除については、Ubuntu 24.04向けのfail2banガイドで説明しています。

遠隔 VPS における遅延とコーデックの選択

遅延は地理的な距離で決まり、設定で解消することはできません。ITU-T G.114 では、通常の会話における片方向の遅延を 150 ms 未満に抑えることを推奨し、約 400 ms までは引き続き使用可能としています。電話機からの音声は VPS を経由してトランクプロバイダーへ送られるため、VPS の地域を誤ると、その経路を 2 回分負担することになります。VPS は電話機の近く、またはプロバイダーの近くに配置してください。両者の条件が異なる場合は、通常、ジッターが最も大きくなりやすい一般向けインターネットを通る区間を優先し、電話機の近くに配置します。

コーデックの選択によって、通話ごとの帯域幅が決まります。ここで扱う各コーデックは 20 ms ごとにパケットを送信します。これは 1 秒あたり 50 パケットに相当し、各パケットには音声ペイロードに加えて、IP、UDP、RTP のヘッダーが 40 bytes 付加されます。

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 は、ほとんどのトランクで標準的に使用されます。そのペイロードは 64 kbps で、ヘッダーを含めると、通話中は各方向に 80 kbps 必要です。Opus は 24 kbps の場合 40 kbps となり、G.729 は音質と CPU 時間を犠牲にして 24 kbps まで削減できます。これらの数値は実測値ではなく、ペイロードのレートに、1 秒あたり 50 パケット分の 1 パケット 40 bytes のヘッダーを加えた計算値です。Ethernet または VLAN のフレーム処理によって、実際の回線上ではさらに少し増えます。

トランスコードには CPU を使用します。電話機とトランクの両方が ulaw に対応している場合は、ulaw のみを許可してください。Asterisk は音声を変換せず、そのまま通過させます。Opus はパケット損失の多いリンクでも良好に動作しますが、Opus と G.711 の間のトランスコードには外部の codec_opus モジュールが必要です。このモジュールは make menuselect で選択しますが、デフォルトではビルドされません。

動作しない場合とログに表示される文字列

呼び出しは接続されるが、音声が聞こえない場合。 RTP が到着していません。rtp.conf の範囲が、ファイアウォールで開放した範囲と一致することを確認します。通話を発信しながら sudo tcpdump -ni any udp portrange 10000-10200 でパケットを監視します。パケットがまったく届かない場合は、ファイアウォールまたはプロバイダー側のネットワークファイアウォールがパケットを破棄しています。

音声が一方向にしか流れない場合。 一方の側が、受信できないアドレスへ RTP を送信しています。これはポートではなく、アドレスの問題です。VPS のインターフェースにパブリックアドレスが直接設定されている場合、NAT の処理は不要です。プロバイダーが VPS にプライベートアドレスを割り当て、1 対 1 のパブリックアドレスマッピングを提供している場合は、トランスポートにパブリックアドレスを設定し、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 と表示される場合。 IP アドレスまたはユーザー名に一致するエンドポイントが見つかりませんでした。スキャナーからの要求であれば正常な動作であり、fail2ban が処理します。自分のプロバイダーからの要求であれば、プロバイダーが接続元として使用するアドレスが identify セクションに記載されていません。

登録状態が Rejected の場合。 プロバイダーが auth セクションの認証情報を拒否しました。CLI で pjsip set logger on を実行し、1 件の REGISTER とその応答を監視します。その後、client_uriusername をプロバイダーから発行された値と比較します。

ログに有用な情報がまったくない場合。 Asterisk はデフォルトで、notice レベル以上を messages.log に出力します。問題を再現している間だけ core set verbose 4pjsip set logger on でログレベルを上げ、その後は両方を無効にします。SIP ロガーはすべてのパケットを記録するためです。

公開する前に

PBX は、他のセルフホスト対象とは異なります。Web アプリケーションが壊れても、発生するのは 1 ページ分の障害です。しかし PBX が侵害されると、眠っている間にも数時間で電話料金が発生します。他の用途には使わない VPS で運用し、5060 は既知のアドレスからの通信だけに制限し、すべての内線にランダムな Secret を設定し、トランクアカウントには利用上限を設定してください。サーバー全体には、公開サーバーと同じ基本対策が必要です。VPS ホスティングの安全性を確認するこの記事で、その内容を説明しています。

FAQ

自己ホスト型 VoIP サーバーで開放する必要があるポートは何ですか?

UDP および TCP の SIP シグナリングにはポート 5060、SIP over TLS を使用する場合はポート 5061 が必要です。RTP メディアには UDP ポートの範囲も必要です。Asterisk のサンプル rtp.conf では 10000 から 20000 を使用し、コンパイル時のデフォルト値は 5000 から 31000 です。1 つの通話で範囲内のポートを 2 つ使用するため、200 ポートの範囲で 100 件の同時通話を処理できます。RTP の範囲は UDP として開放し、5060 は全世界に開放せず、プロバイダーのアドレスと自分のネットワークに制限してください。

Asterisk は単独でインストールすべきですか、それとも FreePBX を使用すべきですか?

攻撃対象領域を小さくし、git で管理できる設定ファイルを使用したい場合は、素の Asterisk をインストールしてください。ダイヤルプランを自分で記述する必要があります。内線、ボイスメール、コールキューを GUI で管理したい場合は、FreePBX をインストールしてください。2026 年 8 月時点で、FreePBX 17 のインストーラーは標準状態の Debian 12 マシンを想定し、Asterisk、Web サーバー、データベースサーバー、PHP をインストールします。そのため、専用の VPS を用意してください。FreePBX は管理対象の設定ファイルを再生成するため、手動編集はその _custom ファイル内で行ってください。

通話接続後に音声が聞こえないのはなぜですか?

シグナリングは機能していますが、メディアが通っていません。SIP はポート 5060 で通話を確立し、音声は RTP の範囲内のポートへ送信される別の UDP フローです。何らかの機器がその通信を破棄しています。rtp.conf の範囲がファイアウォールで開放した範囲と一致していることを確認してください。サーバー上のファイアウォールだけでなく、プロバイダーのネットワークファイアウォールも確認します。通話中に sudo tcpdump -ni any udp portrange 10000-10200 を実行してください。パケットがない場合は、到着前にブロックされています。

SIP のブルートフォース攻撃と料金詐取を止めるにはどうすればよいですか?

すべての内線に長くランダムな Secret を設定し、内線番号と一致する値は使用しないでください。トランクで使用する context は、外線発信が可能な context と分離してください。これにより、着信通話から自分のアカウントを使って外線発信されることを防げます。ポート 5060 へのアクセスは、プロバイダーのアドレスに制限してください。fail2ban の asterisk jail を有効にしてください。これは /var/log/asterisk/messages を読み取り、No matching endpoint found の失敗を発生させたアドレスを ban します。そのうえで、プロバイダー側で利用上限を設定し、使用しない国際通話先をブロックしてください。残りの対策が失敗した場合に損失額を制限できるのは、この制御だけです。

遠隔地のリージョンにある VPS は通話品質に悪影響を与えますか?

はい。音声は、電話から VPS までの区間と、VPS からトランクプロバイダーまでの区間という 2 つの経路を通るためです。ITU-T G.114 は片方向の遅延を 150 ms 未満にすることを推奨しています。配置の悪い VPS では、距離だけでその遅延許容量の大部分を消費することがあります。電話に近いリージョンを選んでください。電話から VPS までの区間は通常、ジッターが最も大きくなりやすい一般向けインターネットを経由するためです。コーデックの選択で遅延は解消できません。変わるのは帯域幅だけです。そのため、G.729 はデータ量を削減しますが、200 ms の経路を改善することはできません。

#voip#asterisk#freepbx#sip#self-hosting