おはよう君需要なし

求不得苦な日々

OpenWRT(LEDE)で HUAWEIのモバイルルーターを使用する

はじめに

家には光ファイバーによる固定回線があるんですが、 公開サーバーを建てるにあたってその固定回線に迷惑がかからないように、 ゲートウェイからセグメントを変えてネット環境を構築したいなと思いました。

そこで目をつけたのが、モバイル回線です。今回はモバイルルーターである、 HUAWEIの「504HW」を使用できるようにしていきます。

LinuxからのHUAWEIモバイルルーターの利用

基本的にソフトバンク系のPocket WiFiなどで使用されてきた HUAWEI製のLTEモバイルルーターは対応OSがWindows, Macとされていて、 Linux用のドライバは明に公開されていません。

しかし、どうもグローバル版のLinux用ドライバを使用することができるようで、 ググってみると結構情報が出てきます。

sunatomo.blogspot.com

500番台のモバイルルーターはどうも「GL04P」などと同じように、 「HUAWEI Data Cards Linux Driver」を使用することでLinux側からも利用可能みたいです。

調べてみるとWiMAXモバイルルーターはつなぐとRNDISでつながるらしく、 (つまりスマホテザリングしているのと同じ繋がり方)挿すだけで使えるようになるらしいです。羨ましい。

OpenWRTでスマホテザリングを使用するのはRNDISのドライバをopkg入れるだけみたいですね。 HUAWEI P9でやってみましたが、ちゃんと使えました。

HUAWEI Data Cards Linux Driverのビルド

ここが鬼門です。今回使用する「WZR-HP-AG300H」という機材はCPUのアーキテクチャMIPSで、 (気合で突破する方法を除き、)クロスコンパイルする必要があります。 どうも過去の自分の記事を読むとこれを実施しているようですが

nodemand.hatenablog.com

手順を残しておらず、呆れ果てました。今回はちゃんと書きます。

使えるKernelのバージョンに制限がある

今回色々と試してみた結果、使えるLinux Kernelのバージョンが4.4あたりまでということです。 つまり、LEDE 17.01.6が限度のようでした。

OpenWRT 18, 19 では Kernel 4.9 や 4.14 を使用しているのでそもそもビルドすることができませんでした。 具体的には、net_deviceの仕様が変わっており、net_device has no member named trans_start エラーを突破できません。

ググって軽く見つかるワークアラウンドを試してみるとビルドは通るものの、kernel panicでOSごと落ちてしまいました。 カーネルの非互換恐ろしや・・・

LEDE 17.01.6用にビルドする

というわけで、Kernel 4.4を採用しているLEDE 17.01.6用にビルドしていきます。 前回の記事でも確かLEDE 17.01.6を使用していた気がします。

SDKの準備

OpenWRT(LEDE)用のクロスコンパイル環境を整えるのは簡単です。 OpenWRTがすでにビルド済みの環境を提供してくれていて、対応するバージョンのSDKをダウンロードして展開するだけです。

OpenWrt Project: Using the SDK

今回は上記サイトより、 lede-sdk-17.01.6-ar71xx-generic_gcc-5.4.0_musl-1.1.16.Linux-x86_64.tar.xz をダウンロードしました。

使用する機材が WZR-HP-AG300H なので ar71xxsdkをダウンロードしましたが、 ここは機材によって変える必要があります。適宜読み替えてください。

展開する

私はWindowsユーザーなのでWSL2上に環境を構築しました。

tar xvf lede-sdk-17.01.6-ar71xx-generic_gcc-5.4.0_musl-1.1.16.Linux-x86_64.tar.xz

として、適当なフォルダに展開しました。この先展開先を /path/to/sdk/ と表します。適宜読み替えてください。

HUAWEIドライバのダウンロード

適当なサイトから「HUAWEI Data Cards Linux Driver」をダウンロードしてください。 もう公式サイトからは提供されていないため、2次配布されているサイトからダウンロードする他ありません。

tar zxf Linux\ Driver\ 4.19.19.00.tar.xz 

として、ダウンロードしたドライバを展開します。 すると中に driver/ndis_driver/ndis_src というフォルダがあるので、

cp -r Linux\ Driver\ 4.19.19.00.tar/driver/ndis_driver/ndis_src ~/

として適当な作業フォルダにコピーします。 今後の作業はこのフォルダにて行います。

cd ~/ndis_src

ソースコードの修正

このままだとクロスコンパイルできないので、クロスコンパイル用に修正していきます。 まずは src/Makefile

KVER            := $(shell uname -r)
# KDIR          := /lib/modules/$(KVER)/build
# KDIR          := /path/to/sdk/lede-sdk-17.01.6-ar71xx-generic_gcc-5.4.0_musl-1.1.16.Linux-x86_64/build_dir/target-mips_24kc_musl-1.1.16/linux-ar71xx_generic/linux-4.4.153
KMISC           := /lib/modules/$(KVER)/kernel/drivers/usb/net
KEXT          := $(shell echo $(KVER) | sed -ne 's/^2\.[567]\..*/k/p')o

Makefile冒頭のmake用の変数を修正していきます。どうせ一度しかビルドしないので直書きしてしまいましたw

modules:
        #$(PWD)/src/add_header.sh  "modules" "$(KDIR)/include/linux/usb"        # $(MAKE) -C $(KDIR) SUBDIRS=$(PWD)/src modules
        $(MAKE) -C $(KDIR) SUBDIRS=$(PWD)/src ARCH=mips CROSS_COMPILE=mips-openwrt-linux- modules
        strip --strip-debug hw_cdc_driver.$(KEXT)

Makefileのmodules ターゲットを修正しました。 具体的には make を実行する際に ARCH=mips CROSS_COMPILE=mips-openwrt-linux- オプションを指定します。

次にソースコードです。 src/hw_cdc_driver.c を修正します。

135行目

// #include <linux/unaligned/access_ok.h>

2718行目

        // dbg ("can't kmalloc dev");

それぞれコメントアウトします。

ビルドの実行

ビルドを実行する前に、クロスコンパイル用のgccにPATHを通します。

export PATH=/path/to/sdk/lede-sdk-17.01.6-ar71xx-generic_gcc-5.4.0_musl-1.1.16.Linux-x86_64/staging_dir/toolchain-mips_24kc_gcc-5.4.0_musl-1.1.16/bin:$PATH
export STAGING_DIR=/path/to/sdk/lede-sdk-17.01.6-ar71xx-generic_gcc-5.4.0_musl-1.1.16.Linux-x86_64/staging_dir/

これでビルドできるはずです。 makeしてみましょう

make modules

LEDEへのカーネルモジュールコピー

そして出来上がったカーネルモジュールをコピーします。

scp src/hw_cdc_driver.ko root@XXX.XXX.XXX.XXX:/root/

で、コピーされたファイルを /lib/modules/カーネルバージョン/ フォルダに配置します。(私の場合は /lib/modules/4.4.153/

配置が完了したら、

modprobe hw_cdc_driver

でモジュールがロードできたら完了です。 もしかすると mii が足りないと言われるので、 opkg install kmod-miimiiをインストールしてください。

あとは、モバイルルーターが接続されたときにCDROMとしてマウントされてしまうのを防ぐために、 usb_modeswitch を導入します。

opkg install usb-modeswitch

で導入できます。これでモバイルルーターを接続すると eth2 として認識されるはずです。

完成!モバイルネットワーク環境

f:id:yoh_mar28:20200815173736j:plain
右から504HW, WZR-HP-AG300H, ThinkPad X220

こんな感じになりました。 504HWがソフトバンクの4G回線を拾い、LEDEにIPが振られローカルネットワークから出られるようになりました。

2重ルーター(NAT)になるのが気持ち悪いですが、まぁ仕方ない。 (事業者から振られているのがプライベートIPなので更に段数は増えるか?)

終わりに

以前はこの方法でいけたので今回もなぞってやってみました。 ちょっと不安なのがLinuxカーネルのバージョンの都合上、 サポート切れのLEDEを使用しなければならないことです。

OpenWRTの19系を使用したかったのですが、Linux力が足りず、カーネルモジュールをうまくビルドできませんでした。 (モジュール自体はビルドできたが、使用しようとするとカーネルパニックで落ちる)

まぁあくまで一時的な利用に控えようと思います。

それはそれとして、2年前構築したときはグローバルIPが降ってきてた気がするんですが、 最近ではプライベートIPしか降ってこないんだろうか・・・? 困る・・・