Windows 11 + SoftEther + Ubuntu VM + Asteriskで自宅SIPサーバーを構築したメモ
目的
自宅のWindows 11マシン上にLinux VMを立て、Asteriskで最小構成のSIPサーバーを作成しました。 まずはLAN内でWindowsとスマホのソフトフォンを登録し、内線101 / 102で相互通話できるところまでを目標にしました。
- LAN内でWindowsとスマホのソフトフォンを登録できる
- 内線101 / 102で相互通話できる
- SoftEther VPN経由の端末からも利用できるようにする
- 既存のApache / VPN構成は維持する
※この記事では、IPアドレス、DDNS名、ユーザー名、パスワードなどの固有情報は記事用にマスクしています。 サンプルのパスワードはそのまま使わず、実運用では必ず強い値に変更してください。
構成
Windows 11上にSoftEther VPN ServerとHyper-Vを置き、Hyper-V上のUbuntu VMにAsteriskを入れました。 Ubuntu VMはHyper-Vの外部仮想スイッチで公開側LANに直接参加させています。
[Internet]
|
[モデム兼ルーター / NAT]
├─ [Apacheサーバー] 192.168.xxx.xxx
├─ [Windows 11] 192.168.xxx.xxx
│ ├─ SoftEther VPN Server
│ └─ Hyper-V
│ └─ Ubuntu VM 192.168.xxx.xxx
│ └─ Asterisk
└─ [内側ルーター]
└─ [家庭内端末] 192.168.xxx.0/24
VPN側
- SoftEther SecureNATを利用
- VPNクライアント帯: 192.168.xxx.0/24
- 仮想ホストIP: 192.168.xxx.xxx
- DHCP配布範囲: 192.168.xxx.xxx - 192.168.xxx.xxx
採用したソフト
VPN
- SoftEther VPN Server
- Windows 11上に構築
SIP / PBX
- Asterisk
- Ubuntu VM上に構築
ソフトフォン
- Windows: Linphone
- スマホ: Linphone
Ubuntu VMのネットワークを外部スイッチに変更
最初、Hyper-VのVMはNAT側にいて172.28.x.xのIPを取っていました。 この状態だとLAN内の他端末から直接SIP登録しづらいため、Hyper-Vの仮想スイッチを外部仮想スイッチへ変更しました。
変更後のIPは次のコマンドで確認しました。
ip -4 a
結果、Ubuntu VMが公開側LANのアドレスを持ち、LANに直接参加する形になりました。
192.168.xxx.xxx/24
Asteriskをインストール
途中、aptの依存関係が壊れていてそのままでは入らなかったため、先にパッケージ状態を復旧してからAsteriskを入れました。
aptの復旧
sudo apt update
sudo apt --fix-broken install
sudo dpkg --configure -a
インストール
sudo apt install -y asterisk
状態確認
sudo systemctl status asterisk --no-pager
sudo ss -lunp | grep 5060
- asterisk.serviceがactive (running) になっている
- 0.0.0.0:5060/udpをAsteriskがListenしている
Asteriskの最小設定
今回はPJSIPを使い、内線101と102を用意しました。 SIP登録後に通話とメッセージ確認までできるよう、最小限のendpoint / auth / aorとdialplanを設定しています。
pjsip.conf
sudo tee /etc/asterisk/pjsip.conf > /dev/null <<'EOF'
[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0:5060
[101]
type=endpoint
context=internal
message_context=messages
disallow=all
allow=ulaw
allow=alaw
auth=101
aors=101
direct_media=no
rtp_symmetric=yes
force_rport=yes
rewrite_contact=yes
callerid="101" <101>
[101]
type=auth
auth_type=userpass
username=101
password=pass101
[101]
type=aor
max_contacts=1
remove_existing=yes
[102]
type=endpoint
context=internal
message_context=messages
disallow=all
allow=ulaw
allow=alaw
auth=102
aors=102
direct_media=no
rtp_symmetric=yes
force_rport=yes
rewrite_contact=yes
callerid="102" <102>
[102]
type=auth
auth_type=userpass
username=102
password=pass102
[102]
type=aor
max_contacts=1
remove_existing=yes
EOF
extensions.conf
sudo tee /etc/asterisk/extensions.conf > /dev/null <<'EOF'
[internal]
exten => 101,1,Dial(PJSIP/101,20)
same => n,Hangup()
exten => 102,1,Dial(PJSIP/102,20)
same => n,Hangup()
[messages]
exten => 101,1,NoOp(Message for 101)
same => n,Set(MESSAGE(from)=sip:102@192.168.xxx.xxx)
same => n,MessageSend(pjsip:101,${MESSAGE(from)})
same => n,Hangup()
exten => 102,1,NoOp(Message for 102)
same => n,Set(MESSAGE(from)=sip:101@192.168.xxx.xxx)
same => n,MessageSend(pjsip:102,${MESSAGE(from)})
same => n,Hangup()
EOF
反映
sudo systemctl restart asterisk
Asterisk側の確認コマンド
CLIに入る
sudo asterisk -rvv
PJSIPの確認
pjsip show endpoints
pjsip show contacts
pjsip show transports
SIP / RTPログ確認
pjsip set logger on
rtp set debug on
Linphoneの設定
Windows側101
Username: 101
Password: pass101
Domain: 192.168.xxx.xxx
Display name: 101
Transport: UDP
Authentication ID: 101
Registrar URI: sip:192.168.xxx.xxx:5060
Outbound SIP Proxy URI: 空欄
スマホ側102
Username: 102
Password: pass102
Domain: 192.168.xxx.xxx
Display name: 102
Transport: UDP
Authentication ID: 102
Registrar URI: sip:192.168.xxx.xxx:5060
Outbound SIP Proxy URI: 空欄
UFWの設定
LANとVPNの両方からSIP登録とRTP音声を通せるようにしました。 5060/udpはSIP登録、10000-20000/udpはRTP音声用です。
sudo ufw reset
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow from 192.168.xxx.0/24 to any port 22 proto tcp
sudo ufw allow from 192.168.xxx.0/24 to any port 5060 proto udp
sudo ufw allow from 192.168.xxx.0/24 to any port 10000:20000 proto udp
sudo ufw allow from 192.168.xxx.0/24 to any port 5060 proto udp
sudo ufw allow from 192.168.xxx.0/24 to any port 10000:20000 proto udp
sudo ufw enable
sudo ufw status verbose
- 5060/udp: SIP登録
- 10000-20000/udp: RTP音声
- LAN側セグメントからSIP / RTPを許可
- VPNクライアント帯からSIP / RTPを許可
動作確認の流れ
LAN内での確認
- WindowsのLinphoneで101を登録
- スマホのLinphoneで102を登録
- pjsip show contactsで両方見えることを確認
- 101から102に発信
- 102から101に発信
- 双方向で音が聞こえることを確認
VPN経由での確認
- スマホをSoftEther VPNに接続
- VPN側IPがVPNクライアント帯になっていることを確認
- Linphoneの接続先はUbuntu VMのLAN側IPのままにする
- 登録 / 発信を確認
ハマったポイント
Hyper-VのVMがNAT配下にいた
最初はVMのIPが172.28.x.xになっていました。 このままだとSIPの確認や他端末からの到達性が面倒だったため、外部仮想スイッチに切り替えてLAN側IPを持たせました。
外部スイッチに変えた直後、NICが死んだように見えた
切り替え直後にloしか見えず、eth0がNO-CARRIER / state DOWNになりました。 Hyper-V側で実NICに正しくつながっていなかったため、外部スイッチの物理NICを見直して再接続しました。
Asteriskのインストール時にapt依存関係が壊れていた
apt install asteriskが失敗し、apt --fix-broken installを要求されました。 aptの状態を直してからAsteriskをインストールしました。
SoftEtherはつながるのにスマホVPNが認証失敗した
スマホからVPN接続すると「認証に失敗しました」と表示されました。 SoftEtherのDefault Virtual HUBが未設定だったため、IPsec / L2TP設定でDefault Virtual HUBをHOMEVPNに設定しました。
443はApacheが使っていたのでSoftEther側には使えなかった
Apacheがすでに443を使っていたため、Apacheは443、SoftEtherは5555 / 992、スマホVPNはUDP 500 / 4500 / 1701に分けました。
SIP登録はできるのに音が聞こえなかった
呼び出しや着信通知はできるのに音声が聞こえない状態になりました。 direct_media=no、rtp_symmetric=yes、force_rport=yes、rewrite_contact=yesを設定し、UFWで10000-20000/udpを許可しました。
101 / 102が登録済みなのに再登録で403 Forbiddenになった
max_contacts=1に対して古いcontactが残っていたため、remove_existing=yesを追加しました。
LinphoneのチャットメッセージがAnonymousになった
通話は101 / 102で見えるのに、メッセージだけAnonymous扱いになりました。 message_context=messagesを設定し、MessageSend() の前にMESSAGE(from) を明示しました。
VPN経由端末はUFWを開けても最初は登録できなかった
VPN接続でVPN側IPは取れているのにSIP登録できませんでした。 UFWの許可元にVPNクライアント帯が入っていなかったため、VPN帯から5060/udpと10000-20000/udpを許可しました。
最終的に動いた構成
- Asterisk: Ubuntu VM上で稼働
- Windows Linphone: 101
- スマホLinphone: 102
- LAN内通話OK
- VPN経由でも登録 / 通話OK
- メッセージ送信時のAnonymousも解消
まとめ
今回の構成では、最初から全部を一気にやろうとせず、Ubuntu VMをLANに直接出すところから順に確認したのが一番分かりやすかったです。
- Ubuntu VMをLANに直接出す
- Asteriskを最小構成で起動する
- Linphoneで101 / 102を登録する
- 通話を通す
- UFWを戻す
- VPNクライアント帯を許可する
- メッセージ表示を整える
特にハマりやすかったのは、Hyper-Vのネットワーク方式、SoftEtherのDefault Virtual HUB、UFWのRTP開放、Asteriskのmax_contacts、MESSAGEの送信元表示でした。
参考用コマンド一覧
Asterisk状態確認
sudo systemctl status asterisk --no-pager
sudo ss -lunp | grep 5060
sudo asterisk -rvv
Asterisk CLI
pjsip show endpoints
pjsip show contacts
pjsip show transports
pjsip set logger on
rtp set debug on
Ubuntu IP確認
ip -4 a
ip route
UFW確認
sudo ufw status verbose
sudo ufw status numbered