ひかり電話を直収したFreePBX(Asterisk)でTLSを有効化するにはどうすれば良いかという話。
もくじ
前提となる環境
サーバー
RasberryPi 5 8GB
Raspberry Pi OS Lite 12.11
FreePBX 17.0.19.28
Asterisk 22.2.0
クライアント
MicroSIP 3.21.4
Linphone Desktop 5.3.0
証明書の用意
秘密鍵: _.example.com.pem
公開鍵: _.example.com.crt
中間証明書: _.example.com.buldle.crt
がそれぞれ必要。証明書の取得方法は割愛。
今回はLet’s Encryptで取得したワイルドカード証明書(*.example.com)を使う。
FreePBXの設定
[設定]-[Asterisk SIP設定]を開く
[SIP Settings(can_pjsip)]タブを開き、tls- 0.0.0.0を[はい]に
Portを5061(標準そのまま)に
[TLS/SSL/SRTP Settings]項目内の3つのファイルを設定する。
CA Chain File: /etc/asterisk/keys/_.example.com.buldle.crt; 中間証明書
Certificate File: /etc/asterisk/keys/_.example.com.crt; 公開鍵
Private Key File: /etc/asterisk/keys/_.example.com.pem; 秘密鍵
その他オプション
SSL Method: tlsv1_2 ; TLS1.2で接続するように
Verify Client: いいえ ;クライアント、サーバー認証を無効に
Verify Server: いいえ
TLS Versionがデフォルト(tlsv1)のままだと、Linphoneがtlsv1を拒否するため接続出来ない。詳細は不明だが、tlsv1にするとtlsv1_1やtlsv1_2での接続を受け付けない模様。
ファイル自体は事前にWinSCP等で適切なフォルダにアップロードして権限設定も確認しておく必要がある。
中間証明書が読み込まれない問題
Asteriskを再起動したら、opensslで接続してみる
echo | openssl s_client -connect sip.example.com:5061 2> /dev/null
CONNECTED(00000003)
---
Certificate chain
0 s:CN = *.example.com
i:C = US, O = Let's Encrypt, CN = R10
a:PKEY: rsaEncryption, 3072 (bit); sigalg: RSA-SHA256
v:NotBefore: Jul 12 23:03:01 2025 GMT; NotAfter: Oct 10 23:03:00 2025 GMT
---
Server certificate
-----BEGIN CERTIFICATE-----
~~~(省略)~~~
-----END CERTIFICATE-----
subject=CN = *.example.com
issuer=C = US, O = Let's Encrypt, CN = R10
---
No client certificate CA names sent
Client Certificate Types: RSA sign, DSA sign, ECDSA sign
Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:ed25519:ed448:rsa_pss_pss_sha256:rsa_pss_pss_sha384:rsa_pss_pss_sha512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA224:RSA+SHA224:DSA+SHA224:DSA+SHA256:DSA+SHA384:DSA+SHA512
Shared Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:ed25519:ed448:rsa_pss_pss_sha256:rsa_pss_pss_sha384:rsa_pss_pss_sha512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA224:RSA+SHA224:DSA+SHA224:DSA+SHA256:DSA+SHA384:DSA+SHA512
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 2066 bytes and written 427 bytes
Verification error: unable to verify the first certificate
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 3072 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-GCM-SHA384
Session-ID: 33D~~~(省略)~~~
Session-ID-ctx:
Master-Key: CAD~~~(省略)~~~
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1756225173
Timeout : 7200 (sec)
Verify return code: 21 (unable to verify the first certificate)
Extended master secret: yes
---
Verification error: unable to verify the first certificate
と表示されているので、証明書の検証がエラーになっている。
これは証明書自体は登録されているが、中間証明書がなく、上位のルート証明書を検証出来ないために起こる。
AsteriskのCLIを起動して
sudo asterisk -vvvvcr
TLSトランスポートのconfigを確認する
raspi*CLI> pjsip show transport 0.0.0.0-tls
Transport: <TransportId........> <Type> <cos> <tos> <BindAddress....................>
==========================================================================================
Transport: 0.0.0.0-tls tls 3 96 0.0.0.0:5061
ParameterName : ParameterValue
===================================================================
allow_reload : false
allow_wildcard_certs : No
async_operations : 1
bind : 0.0.0.0:5061
ca_list_file :
ca_list_path :
cert_file : /etc/asterisk/keys/_.example.com.crt
cipher :
cos : 3
domain :
external_media_address : 114.x.x.x
external_signaling_address : 114.x.x.x
external_signaling_port : 0
local_net : 60.x.x.x/255.255.255.252
local_net : 118.x.x.x/255.255.0.0
local_net : 192.168.x.x/255.255.255.0
method : tlsv1_2
password :
priv_key_file : /etc/asterisk/keys/_.example.com.key
protocol : tls
require_client_cert : No
symmetric_transport : false
tcp_keepalive_enable : true
tcp_keepalive_idle_time : 30
tcp_keepalive_interval_time : 1
tcp_keepalive_probe_count : 5
tos : 96
verify_client : No
verify_server : No
websocket_write_timeout : 100
cert_fileとpriv_key_fileは読み込まれているが、ca_list_fileが読み込まれていない…
なお、この状態でもMicroSIPはサーバー証明書の検証をしない(非対応の)ため、TLSで接続出来てしまう。
中間証明書の設定を追加する
FreePBXのConfig Editの方を覗いても、~bundle.crtが指定された形跡もないので、手動で設定を追加する。
[アドミン]-[Asterisk Custom Configuration Files]-[pjsip.transports_custom_post.conf]を開き、以下を入力する。
[0.0.0.0-tls](+)
ca_list_file=/etc/asterisk/keys/_example.com.buldle.crt
Asteriskを再起動してさっきと同じコマンドを入れる
echo | openssl s_client -connect sip.example.com:5061 2> /dev/null
CONNECTED(00000003)
---
Certificate chain
0 s:CN = *.example.com
i:C = US, O = Let's Encrypt, CN = R10
a:PKEY: rsaEncryption, 3072 (bit); sigalg: RSA-SHA256
v:NotBefore: Jul 12 23:03:01 2025 GMT; NotAfter: Oct 10 23:03:00 2025 GMT
1 s:C = US, O = Let's Encrypt, CN = R10
i:C = US, O = Internet Security Research Group, CN = ISRG Root X1
a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
v:NotBefore: Mar 13 00:00:00 2024 GMT; NotAfter: Mar 12 23:59:59 2027 GMT
---
Server certificate
-----BEGIN CERTIFICATE-----
~~~(省略)~~~
-----END CERTIFICATE-----
subject=CN = *.example.com
issuer=C = US, O = Let's Encrypt, CN = R10
---
Acceptable client certificate CA names
C = US, O = Let's Encrypt, CN = R10
Client Certificate Types: RSA sign, DSA sign, ECDSA sign
Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:ed25519:ed448:rsa_pss_pss_sha256:rsa_pss_pss_sha384:rsa_pss_pss_sha512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA224:RSA+SHA224:DSA+SHA224:DSA+SHA256:DSA+SHA384:DSA+SHA512
Shared Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:ed25519:ed448:rsa_pss_pss_sha256:rsa_pss_pss_sha384:rsa_pss_pss_sha512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA224:RSA+SHA224:DSA+SHA224:DSA+SHA256:DSA+SHA384:DSA+SHA512
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 3413 bytes and written 427 bytes
Verification: OK
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 3072 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-GCM-SHA384
Session-ID: FAA~~~(省略)~~~
Session-ID-ctx:
Master-Key: 382~~~(省略)~~~
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1756225098
Timeout : 7200 (sec)
Verify return code: 0 (ok)
Extended master secret: yes
---
今度は中間証明書とルート証明書もちゃんと表示され、Verification: OKになった。
サーバー証明書の検証に対応しているLinphoneでもきちんと接続出来る。
結局何がダメだったのか
/etc/asterisk 内のconfigをダウンロードしてパス名で検索かけてもそれっぽい文字列は一切ヒットしなかったので、「FreePBXのGUIの設定がconfigに反映されていないのでは?」という結論に。
GUI設定は結構便利だけど、壁にぶち当たった時は結局手動でconfigを読んで、該当箇所の項目名で情報を当たる必要があるので、市販のVoIPルーターみたいに全部お任せ設定でやりたいとなると厳しい。