スポンサーリンク

NGN情報をOpenWrtで取得する

前に書いたdhclientでNGNの情報を取得するテストを、OpenWrt標準のudhcpでやり直し。

ちょっと経緯とか

dhclientが含まれるISC DHCPのメンテナンスは終わっていて、keaへの移行が推奨となっています。

DHCP取得するだけなのでdhclientを使い続けても問題無いと思いますが、今後パッケージなくなったり等もありえるので、標準機能での取得できないかをやってみました。

とりあえず設定してみる

OpenWrtではudhcpが通常使われています。IPv4の設定オプションを見ると、reqoptsとsendoptsがあるので、dhclientの設定を参考に設定してみましたが、うまくいきません。というかどこに取得値保存されているのかがわからず。

調べてみると、OpenWrtのudhcpcは、受信したDHCPオプションをすべて環境変数として、ユーザー定義のスクリプト (/etc/udhcpc.user.d/) に渡してくれるとのことです。
ただコンソールでenvしても値が無いので、ユーザースクリプトで取得した物を全部吐き出させてみましたが、やはりデータが取得できていません。

なので、一度dhclientでの動作を確認します。

最初やってみた残骸
# wanに書いてみた設定
    # 欲しいOptionの指定
    option reqopts '120 121 125 210'
    # 送信するOption (send vendor-class.ntt =~の部分)
    option sendopts '210:06aabbccddeeff'
cat << 'EOF' > /etc/udhcpc.user.d/99-env-dump.sh
#!/bin/sh

env > /tmp/ngn_info.txt
EOF

動作を調べる

tcpdumpでONUへNGN情報取得するDHCPパケットを確認

長いから畳んだ…
tcpdump -i wan -vvn port 67 and port 68
tcpdump: listening on wan, link-type EN10MB (Ethernet), snapshot length 262144 bytes
01:59:40.774573 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none], proto UDP (17), length 328)
    0.0.0.0.68 > 255.255.255.255.67: [udp sum ok] BOOTP/DHCP, Request from 58:27:8c:xx:xx:xx, length 300, xid 0xe8b9df7a, Flags [none] (0x0000)
          Client-Ethernet-Address 58:27:8c:xx:xx:xx
          Vendor-rfc1048 Extensions
            Magic Cookie 0x63825363
            DHCP-Message (53), length 1: Request
            Requested-IP (50), length 4: ***.***.***.***
            Parameter-Request (55), length 5:
              Subnet-Mask (1), Default-Gateway (3), Unknown (120), Classless-Static-Route (121)
              Unknown (125)
            Client-ID (61), length 7: ether xx:xx:xx:xx:xx:xx
            Unknown (124), length 12: 210,xxxxxxxxx,xxxxxxxxxx
01:59:40.793326 IP (tos 0xb8, ttl 255, id 32100, offset 0, flags [none], proto UDP (17), length 402)
    xxx.xxx.xxx.xxx.67 > ***.***.***.***.68: [udp sum ok] BOOTP/DHCP, Reply, length 374, xid 0xe8b9df7a, Flags [none] (0x0000)
          Your-IP ***.***.***.***
          Server-IP xxx.xxx.xxx.xxx
          Gateway-IP xxx.xxx.xxx.xxx
          Client-Ethernet-Address xx:xx:xx:xx:xx:xx
          Vendor-rfc1048 Extensions
            Magic Cookie 0x63825363
            DHCP-Message (53), length 1: ACK
            Subnet-Mask (1), length 4: 255.255.255.252
            Default-Gateway (3), length 4: xxx.xxx.xxx.xxx
            Unknown (120), length 5: 1.118.xxx.xxx.xxx
            Classless-Static-Route (121), length 7: (118.xxx.xxx.xxx/16:xxx.xxx.xxx.xxx)
            Unknown (125), length 76: 210,xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
            Lease-Time (51), length 4: 14400
            Server-ID (54), length 4: xxx.xxx.xxx.xxx
            RN (58), length 4: 7200
            RB (59), length 4: 10800

tcpdumpでRequest確認したところ、120、121、125が追加されている部分のようで、
Unknown (124)となっている部分のデータに210があります。
というわけで、DHCPで送るオプションを完全に勘違いしていたようです。

調べなおしてみると124がVender-class-dataらしく、送ると125を返してくるようです。
で、210って何だったのかというとnttのIDらしい。探してみるとRFC3925

VIVCO (Vendor-Identifying Vendor Class – Option 124)
VIVSO (Vendor-Identifying Vendor-Specific Information – Option 125) 

結論としては、Option124をID210,07,06+MACアドレスというデータで送ると、他のオプションも返してくれるようになるみたいです。

Enterprise Number 210=東 211=西

OpenWrtでNGN情報を取得する設定

というわけで、色々確認して出来上がった設定がこちら

#/etc/config/networkにngn取得用のDHCPインターフェース生やす
config interface 'ngn'
        option proto 'dhcp'
        option defaultroute '0'
        option peerdns '0'
        option multipath 'off'
        option delegate '0'
        option device 'wan'
        option reqopts '120 121 125' # SIP, StaticRoute, VenderDataを要求
        option sendopts '124:000000d20706************' ←*にMACアドレスを入れる

これで取得ができるのですが、取得した内容はそのままどこにも保存されないので、テキストに吐き出すようにします。
option125で取得したデータ列も、そのままでは使いづらいのでデコード処理します。
Geminiがシェルスクリプト頑張ってくれた。

#sshでそのまま貼り付け用

cat << 'EOF' > /etc/udhcpc.user.d/99-ngn-env-dump.sh
#!/bin/sh

DUMP_FILE="/tmp/ngn-info.txt"
env | grep -iE "^(opt|sip|ip|subnet|router|staticroutes|dns)" > "$DUMP_FILE"

if [ -n "$opt125" ]; then
    echo "$opt125" | awk -v file="$DUMP_FILE" '

    function h2d(h,   res, k, p) {
        h = tolower(h)
        res = 0
        for(k=1; k<=length(h); k++) {
            p = index("0123456789abcdef", substr(h, k, 1)) - 1
            res = res * 16 + p
        }
        return res
    }
    
    function hex2ascii(h,   ascii, i) {
        ascii = ""
        for(i=1; i<=length(h); i+=2) {
            ascii = ascii sprintf("%c", h2d(substr(h, i, 2)))
        }
        return ascii
    }
    
    function parse_dns(h,   dns, p_pos, lbl_len, lbl_txt) {
        dns = ""
        p_pos = 1
        while(p_pos <= length(h)) {
            lbl_len = h2d(substr(h, p_pos, 2))
            if(lbl_len == 0) break
            p_pos += 2
            lbl_txt = hex2ascii(substr(h, p_pos, lbl_len*2))
            dns = dns (dns=="" ? "" : ".") lbl_txt
            p_pos += lbl_len*2
        }
        return dns
    }

    {
        hex = $0
        pos = 11
        while (pos < length(hex)) {
            type = substr(hex, pos, 2)
            len = h2d(substr(hex, pos+2, 2))
            val = substr(hex, pos+4, len*2)

            if (type == "c9") {
                mac = ""
                for(i=1; i<=length(val); i+=2) mac = mac (mac==""?"":":") substr(val, i, 2)
                print "opt201=" mac >> file
            }
            else if (type == "ca") {
                print "opt202=" hex2ascii(val) >> file
            }
            else if (type == "cc") {
                print "opt204=" parse_dns(val) >> file
            }
            else if (type == "d2") {
                print "opt210=" parse_dns(val) >> file
            }
            
            pos += 4 + len*2
        }
    }'
fi
EOF

これで /tmp/ngn-info.txt に全部吐き出すことができました。

うまくいくとこんな感じです。

cat /tmp/ngn-info.txt
subnet=255.255.255.252
router=118.***.***.***
opt58=00001c20
opt59=00002a30
staticroutes=118.****.0.0/16 xxx.xxx.xxx.xxx
opt125=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
sipsrv=118.***.***.***
ip=xxx.xxx.xxx.xxx.
opt53=05
opt201=xx:xx:xx:xx:xx:xx
opt202=でんわばんごう
opt204=ntt-east.ne.jp
opt210=www.verinfo.hgw.flets-east.jp

これでSIPやドメイン取得できましたね。

やっと動作を完全に理解した。

他環境でも行けそうですね。

その他参考など

あとから見つかった何か。 https://www.voip-info.jp/index.php/PR-S300SE

Linksys Velop WRT Pro 7 ホーム&ビジネス向け OpenWrt ベース QSDK搭載 WiFi7 トライバンドルーター LN6001-JP NT1516
Wi-Fi 7(802.11be)対応のトライバンドルーターで、OpenWrtベースのQSDKを搭載し、柔軟なカスタマイズが可能です。Qualcomm製1.5GHzクアッドコアCPUと1GB DDR4メモリを備え、最大9239Mbpsの高速...
GL.iNet GL-BE9300(Flint 3) トライバンド Wi-Fi 7 ルーター ワイファイルーター 家庭用 wi-fi 6GHzゲーミング 対応 無線lanルーター wifi7 広範囲カバー 5x2.5Gマルチギガポート 多数端末接続 MLO技術 OpenVPN/WireGuard高速化 (BE9300)
GL.iNet GL-BE9300(Flint 3) トライバンド WiFi 7 ルーター 高速ゲーミングルーター 広範囲通信範囲 5 x 2.5G マルチギガポート 多数デバイス接続 MLO テクノロジー OpenVPN & WireGu...

コメント

タイトルとURLをコピーしました