Asterisk+RTXでひかり電話直収のはなし
まあもう書いてもいいでしょうや。そもそも固定電話ってどうなっちゃうんでしょうね。マスコミは解約をおすすめしたりしててもうね。ちゃんと使えば十分有用だし通話に使うには安いんですけど。
直収とは言ってもちょっと違ったことをやりますので、やりたい人はご参考にどうぞ。なお当然ですがメーカとかキャリアとかにこの記事の内容を問い合わせてはいけません。
ここでネタとして取り上げているのはホーム向けのひかり電話で契約番号はひとつだけです。加えてルータにはヤマハのRTXを使います。
この記事は『わかる人』向けです。万人に推奨されるものではありません。そして長いです。
そもそも
ひかり電話を TA等を使ってAsteriskに収容する場合、下図のような構成になっていると思います。ONUの下にハブを入れるなどして分岐させTAとルータを分けるやりかたです。一般のご家庭ではこんな面倒なことは必要ないのですけども、無理やりレンタルされるルータを使いたくない人はこうしてますよね。
この場合の問題としてはONUに複数の機器を繋ぐのでハブで分けたりして機器が増えること。加えてAsterisk側からみるとインターネット向けのトラフィックはルータに向け、ひかり電話のトラフィックはTAに向けなくてはいけないので静的な経路情報を設定する必要があることです。
注:この接続方法、安直にやるなという記事を書いておきました。
でまあ直収しようという人もいるわけでして、その場合の接続は下図のようになっているはずです。
要はTAを経由せず、Asteriskが直にひかり電話と喋るように接続するのですが、そもそもONU直下のネットワーク部分はLANとは『別な』ものなので、別系統として接続する必要があります。専用に別なNICを増設する感じですね(VLANでもいいんですけども)。
この場合の問題点はNICを増やさないといけないことと、やはり経路制御は別途行う必要がある(とはいえ静的経路を足すだけ)ことです。結構きれいな構成に見えますがこれでもまだ煩雑な気がしません?加えて余計なトラフィックをNIC2側に流さないような配慮も必要となります。
そこで考えたのが以下の構成。めちゃくちゃきれいですよね?
きれいというか単純にインターネット接続のルータがある「だけ」です。これで出来るの?と思いますよね。さっきから図に使っているルータの写真がヤマハのRTXだということに気付きました?RTXならできます。他のルータでもできるかもしれませんが出来そうだと思ったら試してみてください。
RTXでひかり電話を収容するメカニズム(目論見)
ヤマハのRTXにはSIP-NATの機能が備わっています。これを利用してNATビハインドにあるAsterisk Serverをひかり電話のネットワークに出してやろうというわけです。Asterisk Serverとはいえ網からみれば単なるUAなのでNATビハインドのUAから網に繋ぐイメージです。
まずRTXでインターネットに接続している場合、pp(PPPoE)がインターネットとの接続を行っているはずです。これはLAN2(RTX830の場合。要するにWAN側インタフェース。)を使っていますが、PPPoEのトンネル端(pp1)なのでLAN2には直接関係しません。言い換えるとLAN2はこのppのIPアドレスを「知らない」ことになります。
pp1は一般的な接続ではRTX内部でNAT(IPマスカレード)を経由してLANに繋がっており、インターネット接続を提供しています。この部分は「普通に」インターネット接続なのでここでは気にしません。
もちろん、LAN2がDHCPなネットワークに接続されている場合には気にしなくてはいけませんが、ひかり電話+DHCPなISPという構成は通常はあり得ませんので気にする必要はありません。
もしLAN2(外側、WAN側)を他の用途に使っている場合にはaddressをprimalyとsecondlyで使い分ければうまくいくかもしれませんが試してはいません。ここではprimalyアドレスで設定しています。
今回構成するのは図の下の部分です。動作の目論見は簡単といえば簡単で、ひかり電話ではDHCP(v4)でIPアドレスやその他の情報を取得し、SIPサーバにREGISTERすることで電話として使えるようになるので、RTXのDHCP機能でIPアドレスの取得を行い、後ろにあるAsteriskと通信させようというものです。先ほどの図2ではNICを増設することにより、ひかり電話の収容を行い、ひかり電話の『端』をAsteriskにもっていったたわけですが、ひかり電話の『端』だけはRTXに任せてしまおうというわけです。SIPのシグナリングなどのVoIP機能は当然ならがらAsteriskが行います。ただし、AsteriskはNATビハインドにあるので、ひかり電話との接続点そのものはRTXということになります。
このとき先述のようにLAN2はISPの接続にも使われていますが、ISPはPPPoEで繋がれているためLAN2自体のIPアドレスはPPPoEには影響を与えません。
以上の構成により、ひかり電話を含むすべてのトラフィックはRTXに任せることができるようになります。Asterisk Server側では経路を設定する必要はありません。
なおipv6トラフィックもLAN2を経由しますが、今回やってみるひかり電話はipv4のみですのでipv6(IPoE)には影響を与えないはずです。
ひかり電話の情報を取得する
それではまず、ひかり電話の情報を取得しましょう。DHCP(v4)で取得できるのですが、この情報、頻繁に変わることはないようなので手動でやります。Asterisk直収の場合にスクリプト等で自動化している例もありますが、そこまでやる必要はなさそうなので手動で行うことにします。もし、通話できない等の状況が発生したらこの手順から再度手動でやりなおせばすむ話ですので。
要するにこれはUAに対するプロビジョニング情報ですよね。
RTXをNGNモードにして情報を取得する
この段階ではLAN2(RTX830の場合)に対して何も設定されていないものとします。なお、この先ではRTX830の場合というような但し書きはしませんが、RTX830以外の機種でLANインタフェースの名前が異なる場合には自分の環境にあったインタフェース名に読み替えてください。ここではLAN2を例として使います。
以下のコマンドで情報を取得します。
これでLAN2にはDHCPで取得したIPアドレスが設定され、あわせてひかり電話の情報も取得されます。
取得された情報はこのコマンドで表示されます。表示された内容から以下の情報をメモしておきましょう。
これらの情報、単なるDHCPでは取得できずNGNを使用すると設定した場合にのみ取得できます。NGNを使用しない場合にはLAN2は単なるDHCPクライアントとして動作するだけです。
ならばNGNを『使用する』状態で使い続ければよさそうに思えるのですが、ここに落とし穴がありました。謎のREGISTER(SIPの)が出ていることに気付いたのです。
RTXの場合、NGN機能をオンにしているとNGNのSIPを使うようで、ひかり電話契約がある場合には、ひかり電話の情報を取得してくるだけでなくREGISTERを投げることでNGN上で自分のロケーション情報(IPの)を登録しているようです。Wiresharkで観測していて気付きました。これをやられると、ちょっと面倒なことになります。『電話』としてのREGISTERはAsteriskから行うのですが、RTX自体がREGISTERするとcontact情報がAsteriskのものではなく、RTXのものになるため着番がおかしなものになります(*1)。なので、RTX自体によるREGISTERを止めたいのですが、NGN機能をONにしたままREGISTERを止める方法を見つけることができませんでした(sip use ofにしても出る)。知っている人がいたら教えてください。もしNGN機能ONの状態のままLAN2のDHCPを活かすことができれば、ひかり電話の情報はいつでも見られて便利です。
*1: Workaroundはあります。着番がおかしくなるので、おかしな着番に対して処理してやれば使えなくもありません。ただREGISTERが複数個所から飛ぶのは好ましくないと思います。なので、この追及はあまりしませんが何か良い使い方もある気がしなくもなくない。そもそもこの使い方はおかしいのでだめそうです。
RTXのNGNモードをオフにする
情報を取得しメモしたらNGNをオフにしてLAN2を普通のDHCPクライアントにしてしまいます。
NGN機能をオフにしたらRTXを再起動しておいてください。というのもコマンドでオフにしてもREGISTERの送出は止まらないようで出続けていることが観測できたからです。NGNをオフにして再起動するとこれは止まります。
ひかり電話におけるIPアドレスの取得はDHCPということになっているので、これでLAN2に対するIPアドレスの取得や更新は問題がないはずです。
ここで注意(はやめに言っておく)
この先、Asteriskを設定することになるのですが、AsteriskのPJSIPはそのままではファイル(/etc/hosts)からホスト名->IPアドレスを解決することができません。これにはlibunboundが必要となります。ですので、ファイルを使用する場合にはlibunbound-dev(Debian系の場合)をインストールした後、AsteriskをConfigureしてからmakeしなおしておいてください。DNSサーバによる名前解決を使う(ローカルDNSとか)場合には必要ありません。もしローカルDNSサーバを使っている場合にはこの作業は要りません(ローカルに登録する作業は要ります)。
また忘れがちな点として /etc/hosts を書き換えたのに参照されないという場合にはnsswitch.confの確認もお忘れなく。
RTXの設定
RTXを設定します。なお、フィルタやテーブル類は2000番を使用していますが適宜読み替えてください。自分に都合のよい番号を振ってください。
なお、この運用ではNGN設定はオフです。オフにすると都合の悪い環境では、ここで説明している方法は使えません。
また設定類は最低限のものです。フィルタ等は自分で設定してください。ただ、繋がる先はひかり電話のネットワークなのであまり気にする必要はないかもしれませんが。
LAN2設定
IPアドレスはDHCPで取得、LAN2のNATディスクリプタ番号は2000。RIPは送受信ともにオフにしておく。
RIPの注意点
RIPの設定ははグローバルでrip useがデフォルトでoffです。もしonにしている場合にはLAN2(ひかり電話のネットワーク)に対してRIPを流すのも受けるのも良くはないのでip lan2 rip send off, ip lan2 rip recieve offを明示的に入れてあります。
NGN,SIP設定
今のところこの設定で使用。NGNをオンにすると余計なREGISTERが飛ぶのでオフにしている。もしかするとRTX配下にVoIPルータを置くために先っちょからREGISTERする仕様なのかも。そもそもRTXのSIP-NAT機能も汎用とは言っておらず配下に他のヤマハルータを置くためのものとされているので。
経路情報
ひかり電話へのトラフィックを静的に定義します。前に取得した情報からネットワークアドレス(サブネットも)とゲートウェイアドレスを記述してください。ぶっちゃけ東日本だとネットワークは118.177.0.0/16みたいなのになります。このエントリ以外ににデフォルトゲートウェイがppに対して定義されていると思いますが、それはインターネット向けですので、ひかり電話のトラフィックはそちらに流さず⑤のゲートウェイ経由で流すわけです。このゲートウェイアドレスはLAN2に割り当てられたIPアドレスの「先」にありますが、LAN2とは/30のネットワークで繋がっているのでreachableになります。
NATディスクリプタ設定
このNATディスクリプタは、ひかり電話専用に使うので外側アドレスはインタフェースのprimary、SIP-NAT機能を使用する。
静的マスカレードで外からのSIP(5060)とRTP(UDP 10000-11000)のトラフィックはAsteriskへ飛ばす。このときのIPアドレスは当然ながらローカル(LAN内)のAsteriskのアドレス。
なお、RTPのポート番号範囲が上記の例と違う場合には書き換えてください。rtp.confで指定している範囲が対象となります。要は外->内のRTPでAsteriskが扱うレンジは全てAsteriskに飛ばします。
注意としてはヤマハのSIP-NAT機能はSIPのポート番号が5060固定な点です。
Asterisk側の設定
あらかじめ早めに書いておきましたけども、Asteriskはlibunbound付でコンパイルしたものを使ってください。
まずはhosts設定
要はLinux側の設定ですが、/etc/hostsに以下のエントリを書きます。
ドメインは東だと ntt-east.ne.jp ってやつですね。ローカルDNSサーバ等を使用している場合には同様にドメインからIPアドレスを求められるように設定しておいてください。
PJSIPの[system]
disable_rport = yes の設定がsystemセクションに必要です。
PJSIPのACL
あなたがこれをどこに書いているかは、あなたにしかわかりませんので書くべきところに書いてください。pjsip.confかもしれません。
ACLのエントリにpermitで、ひかり電話のネットワークを追加しておきます。/16 の記述が使えます。まあこれは東だと 118.177.0.0/16 あたりです。他の場合もあるみたいなので自分で取得したネットワークを書いてください。SIP上ではこのアドレスが『見える』ので、permitしておかないとACLに引っ掛かります。
トランクの定義
PJSIPでの書き方は好きにすればいいのですが、自分はトランクはトランク毎に書き、pjsip.confでincludeする書き方が好きです。例えば pjsip_trunk_hikarid.conf みたいにしておけばわかりやすいですよね。
必要な情報は以下のような感じです。ヤマハのSIP-NATが5060決め打ちのため、5060の専用のtransportも作ります。
[Tel number]は自局番号ですが、これもDHCPで取得された番号を使用してください。取得された番号以外を使うとたぶんダメですが、試してみる勇気はありません。
今のところこの設定で動作していますが、タイマー関連等は設定を入れるつもりです。
endpointの設定も今のところこれで動作していますが少し調整しようかなとは思っています。
注意点としてはヤマハのSIP-NATはポート5060固定なので、registrationとendpointのセクションではtransportを明示指定しているところです。
なお、セキュリティ絡みで5060ポートを開けておくと危ないんじゃ?と思われるかもしれませんがこの構成でAsteriskはNATビハインドにあります。なので明示的に外->内の5060を設定しない限り、外から5060には到達できません。唯一到達できるのは、ひかり電話のネットワークからだけです。
もし気になるようでしたらppのIPフィルタで5060ブロックを入れておくといいかもしれません。
着信
上の例ではcontextをfrom-hikari-rtxにしています。落ちる先のextenは自局番号になります。
みたいな感じで書けば着信は簡単にできるはずです。もし音声が通らない場合には静的マスカレードのRTPが間違っていないかどうかを確認してください。
キャッチオールしておいて着信先をヘッダから取り出すことも可能です。
Toヘッダを取り出し、頭5文字(<sip:)を削り、そこから自局の桁数分だけ取り出します。例では着信先番号は10桁になっています。
現在の自分の契約が単一番号のため、複数番号契約の着信挙動がわかりませんが、おそらくToヘッダに入るんじゃないかと想像しています。
発信
ふつうに Dial(PJSIP/番号@エンドポイント)をするとFrobiddenを食らいます。なあにこんなものはよくみた挙動です。PPIが足りないだけです。
まずPPIヘッダを足すサブルーチンを書きます。
要するにPPIに<sip:0312345678@ntt-east.ne.jp>みたいなのを足します。自局の情報ですね。
Dialするときにはこれを呼びます。次のような感じ。
PJSIPの動作としてDial時のサブルーチンでヘッダを追加しなければならないのでこうします。
東日本の場合はこれでダイヤルできるはずです。
というわけで
RTXを端、SIP-NATを使ってNATビハインドにAsteriskを置くことで、ひかり電話に直収することができました。SIP-NATを持たないルータの場合にはPJSIPで外側アドレスを明示定義すればうまくいくかもしれません。
ただしこのDHCP+NAT+SIP-NATというのがミソの部分で、『外側』つまり、ひかり電話側のIPアドレスを意識せずにAsteriskを設定できるというのが最大のポイントでして、NATデスクリプタでouterをprimalyにしておけば外側のことは「知らん」ができるわけです。Asteriskに外側IPを設定すると外側が変わった場合に設定しなおさなければになるのを避けているわけです。観測したわけではないので何とも言えないのですがDHCPを使っているものの、割り当てられるIPアドレスは「ほぼ固定」だったりすると他のルータでもうまくいくかもしれません。
DHCPで取得される情報で毎度毎度設定を更新しないとと思い込んでましたが、実際には情報はほぼ変わらないようなので取得した情報で設定してしまえば当分使えそうですし、通常のインターネット接続に足す形でひかり電話を収容できてしまいますから、こんな便利なことはありませんね。
そもそもこの設定部分を自動化したいニーズって何?と考えると挿せば使える機器を「売りたい」というとこしか思いつかないんですよね。そういう人はまあ頑張って。だいたい、設定情報、毎日変わるわけもないし月1で変わるようなもんでもないですし。更新しなければならない情報はDHCPのrenewで、これはRTXに任せておけばいいわけですから今回の方法で良さそう。
え?RTXが高いって?それはまた別なお話。中古で買えば安いしそうそう壊れるもんでもないですよ。一般のご家庭で使うならそんなものすごい性能のは要りませんし。
追記:NGN機能との併用はダメな気がする。RTX自体がREGISTERを投げるものの、投げたら投げっぱなしで何もしない。SIP-NATを無効にして使うとForbiddenを食らう。電話契約があるからREGISTERを投げているように見えるものの、RTX単体では何もしようとしていないので、この機能は下流に何か繋いだ場合のためのものなのかもしれない。いやそもそもRTX830単体ではVoiceの機能を持ってないのにREGISTERをなぜ投げる?データコネクトのため?
投げない設定があればいいのだけども。
→ データコネクト用のようです記事を書きました