IX2215直下にHGWを置いてひかり電話をする【2024年夏版】

# 概要だよ
- UNIVERGE IX2215直下に繋いだHGWと同一リンクにDHCPv6サーバを置くことでNTTからのDHCPv6パケットを偽装するといいよ
- 従来の方法は最新HGWのファームウェアに対応できていなかったよ
- NVR500・510を使うほうが楽だよ。ひかり電話でSIPクライアントを使いたい人（スマホアプリで固定電話を使いたい人）はHGWを使うと楽だからこの記事を見てね。

# 免責

この記事の内容はあくまでも報告の目的で書かれたものです。
動作の保証をするものではなく、また想定されていない利用方法である可能性があることをご留意ください。本内容を実践する場合は全てご自身の責任の下行ってください。本内容を実践した結果生じた損害等如何なる事象に対して著者は一切の責任を持ちません。

:::note alert
ひかり電話を安定して利用できない可能性があるため、研究目的以外の用途（特に緊急通報を行う手段がひかり電話に限定されるような場合）には本内容を実践しないでください。
:::

# イントロ
こんにちは。
UNIVERGEのこと好き好きクラブ[1]の皆さまにおかれましては、自宅等のメインルータにUNIVERGE（特にIX2215）を使っているのではないでしょうか。
また、NTT回線において/56のIPv6を使いたいためだけにひかり電話を契約している方も多いかと思います。
    IX2215でNTT回線を収容するとひかり電話が使いづらくなる問題があります。
せっかくなのでIX2215等をメインルータにしたまま、NTTからレンタルされるHGWを活かしてひかり電話を使う方法をご紹介します。

同様の記事は今まで多種ありますが、最新のHGW（私の検証下ではRX-600KI ver.01.00.0040）は今までの方法では対応していませんでした。

https://qiita.com/yangniao23/items/9be42ee14b0e15b8f4ce

なお、HGWではなく、YAMAHAのNVR500やNVR510を直下に置く方法も別途ありますがその方法は他の記事をご参照ください。NVR500・NVR510をメインルータ直下に置く方が楽で安定しています。

# なぜHGWを活かす必要があるのか
HGWはPBX的な機能を有しています。
この機能はNVR500・NVR510にはありません。（あったら教えてください・・・）
HGWを設置することでSIPクライアントからひかり電話を利用することが簡単にできます。
これはつまり、固定電話を買わずとも、手持ちのスマートフォンで[AGEphone](https://www.ageet.com/agephone)等のアプリを使えばひかり電話を利用できることを意味し、VPNを用いることで遠隔地からでもひかり電話を利用することが理論上可能となります。

ひかり電話の通話料金は電話料金と比較して圧倒的に安く、特にナビダイヤルを利用する際は携帯電話よりもひかり電話が圧倒的に安いため、VPNで自宅に繋いでひかり電話でナビダイヤルにかけるほうがお得です。
HGWを設置することで、自前で[Asterisk](https://www.asterisk.org/)のようなPBXを用意する手間を省くことができるのです。
なお、HGWを使わずにAsteriskでひかり電話を収容したい方はこちらが参考になります。

https://qiita.com/kmorimoto/items/d99cd9edcf7436eea7cc

下記は料金をまとめた表ですが、あくまでも参考です。やはりひかり電話は安い。。。

| 宛先 | ひかり電話 | 携帯電話(povo) |
|:-----------|------------:|:------------:|
| 固定電話宛  | 8.8円／180秒 | 22円/30秒  |
| 携帯電話宛  | 17.6円／60秒 | 22円/30秒  |
| ナビダイヤル| 9.35円／180秒| 11円／20秒 |

ソース

https://flets.com/hikaridenwa/charge/phonecall.html

https://povo.jp/spec/

https://www.ntt.com/business/services/voice-video/freedial-navidial/navidial/price.html

# DHCPv6がないとHGWがうまく動かない
「ひかり電話はIPv4しか使わないため、IX2215からHGWにはIPv4のパケットのみを疎通させればよい。」そのような記事を見かけることがあります。確かにひかり電話はIPv4のみしか利用しませんが、少なくとも最新のHGWでは上記の方法ではひかり電話は利用することができません・・・。おそらく、以前のHGWやファームウェアでは動作したものと思われます。

また、UNIVERGEのDHCPv6サーバ機能を用いてHGWにPD(Prefix Delegation)してあげる方法を紹介している記事がありますが、こちらの方法も最新のHGWではひかり電話を利用することができません。
ひかり電話を利用するためにDHCPv6 オプションとして、HGWには下記の物を渡してあげる必要があるようです。
- Vendor-specific Information (17)
- SIP Servers IPv6 Address List (22)
- DNS recursive name server (23)
- Domain Search List (24)
- Identity Association for Prefix Delegation (25)
- Simple Network Time Protocol Server (31)

IX2215では、対応しているDHCPv6 オプションは23番の「DNS recursive name server」と31番の「Simple Network Time Protocol Server」のみとなり、必要な情報をHGWに渡すことができません。
そのため、IX2215のDHCPv6サーバ機能ではHGWでひかり電話を動作させることができないのです。

# 解決方法
## 概要
DHCPv6サーバが必要なら自前で構築すればよいだけです。
ONUとHGWを直接つないだ時にNTT側のDHCPv6サーバとHGW(DHCPv6クライアント)がどのような情報をやり取りしているかを解析し、自前のDHCPv6サーバで同様のパケットをHGWに送出するようにDHCPv6サーバを構築します。

## HGWとNTT側DHCPv6サーバの通信解析
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510882/c1fb2772-ceff-29d4-c840-e6db3dd43ceb.png)
まずは、通常通りHGWを利用した場合、どのようなDHCPv6パケットがやり取りされているかを解析します。
図のようにONUとHGWの間のパケットをWiresharkで観測します。
この間のパケットを解析する方法は多種あるかと思いますが、私はL2スイッチを間に挟んでポートミラーリングを設定してキャプチャしました。
![ONU-HGW_editted.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510882/c5d4becf-3517-d2e8-b1e0-71486846472f.png)

「dhcpv6」でフィルタリングを行うことによって目的のパケットを見ることができます。
DHCPv6のReplyパケットを覗くと、図のようにNTT網にあるDHCPv6サーバが渡している
各種DHCPv6オプションの内容が分かります。
後ほど自前のDHCPv6サーバを構築する際に必要な情報となりますので、各種中身をメモしておきます。
特に、Vendor-specific Information (17)に関しては、複数個のOptionが
定義されており、Opotion DataやOption Codeを共にしっかりとメモします。
その際のOption Dataの値は16進のバイナリデータのままコピーしておくとよいでしょう。
ちなみに、これらに自身に割り振られた電話番号等が含まれています。

## DHCPv6サーバの構築
Linuxで利用できるDHCPv6サーバとして今回[Kea DHCP](https://www.isc.org/kea/)を利用します。
私はRaspberry Pi 4BのUbuntu Server 22.04 LTSにインストールしました。
インストール手順の詳細は[公式ドキュメント](https://kea.readthedocs.io/en/kea-2.6.0/arm/install.html)を参照してください。
今回はDHCPv6サーバのみ利用するため、全ての機能(DHCPv4サーバ等)をインストールする必要はありません。
```shell
# リポジトリの追加(Kea-2.6.0)
$ curl -1sLf \
  'https://dl.cloudsmith.io/public/isc/kea-2-6/setup.alpine.sh' \
  | sudo -E bash

$ sudo apt update
# DHCPv6サーバのみをインストール
$ sudo apt install isc-kea-dhcp6-server
```
上記が終了し、下記コマンドが実行できればインストール完了です。
```shell
$ kea-dhcp6 -v
2.6.0
```
### configの編集
今回の肝です。先ほどメモした各種DHCPv6 Optionの中身を記述していきます。
各種configの意味は[公式ドキュメント](https://kea.readthedocs.io/en/kea-2.6.0/arm/dhcp6-srv.html)を参照してください。
Option以外にもPDさせるための設定を記述する必要があります。
ドキュメントを見つつ適宜変更してください。
ちなみに、Option codeが201のときのOption dataが何を示しているのかは私は分かりませんでした。（多分NTTの技術資料をちゃんと見ればわかりそうです。）
動作確認済みですが、`"subnet6"`あたりのconfig記述が怪しいため、誤っていると思われる場合は連絡ください。

```json:/etc/kea/kea-dhcp6.conf
{
  "Dhcp6": {
    "interfaces-config": {
      "interfaces": [
        "[DHCPv6サーバを利用するインターフェース名を記述（例:eth0）]"
      ]
    },
    "lease-database": {
      "type": "memfile",
      "lfc-interval": 3600
    },
    "expired-leases-processing": {
      "reclaim-timer-wait-time": 10,
      "flush-reclaimed-timer-wait-time": 25,
      "hold-reclaimed-time": 3600,
      "max-reclaim-leases": 100,
      "max-reclaim-time": 250,
      "unwarned-reclaim-cycles": 5
    },
    "renew-timer": 7200,
    "rebind-timer": 10800,
    "preferred-lifetime": 12600,
    "valid-lifetime": 14400,
    "option-def": [
      {
        "code": 201,
        "name": "unknownOption1",
        "space": "vendor-210",
        "type": "binary"
      },
      {
        "code": 202,
        "name": "telNumber",
        "space": "vendor-210",
        "type": "binary"
      },
      {
        "code": 204,
        "name": "nttDomain",
        "space": "vendor-210",
        "type": "binary"
      },
      {
        "code": 210,
        "name": "venderInfoDomain",
        "space": "vendor-210",
        "type": "binary"
      }
    ],
    "option-data": [
      {
        "name": "vendor-opts",
        "data": "210"
      },
      {
        "always-send": true,
        "data": "[Option codeが201のOption dataを16進数バイナリで記述]",
        "name": "unknownOption1",
        "space": "vendor-210"
      },
      {
        "always-send": true,
        "data": "[Option codeが202のOption dataを16進数バイナリで記述]",
        "name": "telNumber",
        "space": "vendor-210"
      },
      {
        "always-send": true,
        "data": "[Option codeが204のOption dataを16進数バイナリで記述]",
        "name": "nttDomain",
        "space": "vendor-210"
      },
      {
        "always-send": true,
        "data": "[Option codeが210のOption dataを16進数バイナリで記述]",
        "name": "venderInfoDomain",
        "space": "vendor-210"
      },
      {
        "name": "sip-server-addr",
        "code": 22,
        "data": "[メモしたSIPサーバのアドレスを記述]"
      },
      {
        "name": "dns-servers",
        "code": 23,
        "data": "[メモしたDNSサーバのアドレスを記述。カンマ(,)で区切って2つ記入できる（例 2001:db8::a, 2001:db8::b）]"
      },
      {
        "name": "domain-search",
        "code": 24,
        "data": "[メモしたdomain-searchのアドレスを記述。カンマ(,)で区切って2つ記入できる。]"
      },
      {
        "name": "sntp-servers",
        "code": 31,
        "data": "[メモしたSNTPサーバのアドレスを記述。カンマ(,)で区切って2つ記入できる（例 2001:db8::a, 2001:db8::b）]"
      }
    ],
    "subnet6": [
      {
        "id": 1,
        "interface": "[DHCPv6サーバを利用するインターフェース名を記述（例:eth0）]",
        "subnet": "[インターフェースに所属させたいサブネットを記述（例　2001:db8:0:8880::/60）]",
        "pools": [
          {
            "pool": "[サブネットの内HGWに割り振るIPv6アドレス範囲を記述（例　2001:db8:0:8880::/64）]"
          }
        ],
        "pd-pools": [
          {
            "prefix": "[HGWにPDするIPv6アドレスプレフィクスを記述（例　2001:db8:0:8890::）]",
            "prefix-len": [HGWにPDするIPv6アドレスプレフィクス長を数値で記述（例　60）],
            "delegated-len": [HGWから配布するIPv6アドレスプレフィクス長を数値で記述（例　64）]
          }
        ]
      }
    ],
    "loggers": [
      {
        "name": "kea-dhcp6",
        "output-options": [
          {
            "output": "/var/log/kea-dhcp6.log"
          }
        ],
        "debuglevel": 0,
        "severity": "INFO"
      }
    ]
  }
}
```

設定完了後DHCPv6サーバを再起動します。
```shell
$ sudo systemctl restart isc-kea-dhcp6-server.service
```

## IX2215の構築
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510882/ff7a054e-1db0-d6a9-94bc-5082fc5371ac.png)
図中のGE2の1-8の各番号はポート番号を示しています。
ONUをIX2215のGE0を接続し、自前のDHCPv6サーバであるRaspberryPiをGE2のポート5に、HGWをGE2のポート7に接続することを想定しています。
IX2215によってMAP-EやPPPoEを収容し、PC等を接続している想定ではありますが、今回は関係ないため省略しています。
また、HGWの設定やSIPクライアントの接続等を行うためにHGWのLAN端子とGE2のポート8を接続しています。VLANで独立リンクになるように設定します。

ONUから来るIPv4パケットをHGWにBridgeで流せるようにし、一方でIPv6はBridgeしないように設定します。
これはONU(NTT網側)から流れてくるDHCPv6サーバのパケットをHGWで受信しないようにするためです。
ONU(NTT網側)から流れてくるDHCPv6パケットを受け取るのはIX2215であり、DHCPv4のパケットを受け取るのはHGWであることに注意が必要です。
また、自前のDHCPv6サーバであるRaspberryPiがHGWと同一リンクに所属するように設定します。
IX2215においては、HGWやRaspberryPiに対してDHCPv6サーバから情報を取得させるため、MフラグとOフラグを有効にしたRAを送信した上でIPv6通信を許可しています。

まとめると、HGWから見たときに
- IPv4においてはONU・RaspberryPiが同一リンクに存在
- IPv6においてはIX2215・RaspberryPiが同一リンクに存在
する構成となります。

:::note warn
RaspberryPiがONU側からのDHCPv4のパケットを処理しないようにDHCPv4クライアントを無効化してください。
RaspberryPiは今回IPv6通信しか利用しません。
もしDHCPv4パケットを受信してIPv4アドレスを付与されてしまうとHGWにIPv4アドレスが割り当てられないためHGWの挙動が不安定になります。
:::

以下IX2215のconfigです。
```cisco_ios:running-config(一部抜粋)
bridge irb enable
no bridge 1 bridge ipv6
!
ipv6 dhcp client-profile dhcpv6-client
! ひかり電話を使うためには必要のない設定だが、
! IX2215自体はONU側からDHCPv6パケットを受け取っていることを説明するための設定
  option-request dns-servers
  option-request ntp-servers
  shutdown-delay 100
!
device GigaEthernet2
  vlan-group 2 port 5 7
  vlan-group 3 port 8
!
interface GigaEthernet0.0
  no ip address
  ipv6 enable
  ipv6 dhcp client dhcpv6-client
  ipv6 traffic-class tos 0
  bridge-group 1
  no shutdown
!
interface GigaEthernet2:2.0
  description ### For_Hikari_Denwa_WAN ###
  no ip address
  ipv6 nd ra enable
  ipv6 nd ra managed-config-flag
  ipv6 nd ra other-config-flag
  bridge-group 1
  no shutdown
!
interface GigaEthernet2:3.0
  description ### For_Hikari_Denwa_LAN ###
  ip address 192.168.2.2/24
  no shutdown
!
```
上記configでは、HGWはLAN側アドレスとして192.168.2.1/24を設定している想定で、
IX2215が192.168.2.2/24を設定している想定です。

以上で構築は終わりです。

# 正しく動いているかの確認
HGWにアクセスし、「DHCPクライアント取得情報」からIPv4/IPv6アドレスが取得できていること・DNS/SNTPサーバアドレスが取得できることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510882/041a154b-a82f-89f4-80b9-485b0850d6e5.png)
また、「現在の状態」から、ひかり電話が利用可能になっていることも確認しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510882/2b0af483-b8a4-d2d9-75cb-45c4f09c6cb2.png)
あとは通常通りのひかり電話として利用できるので、[AGEphone](https://www.ageet.com/agephone)等のアプリなどのSIPクライアントを接続したり、通常の固定電話機を接続してひかり電話を楽しみましょう。
SIPクライアントを接続する際には、HGWに設定したLAN側のIPアドレス（上記想定では192.168.2.1）を指定してあげます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510882/53a24cee-d2a1-f786-b499-cb4356c62ebe.png)

以上で設定構築が完了となります。不明瞭な点等あればコメントいただければ幸いです。

[1] 「蓮ノ空のこと好き好きクラブ」を文字っている