OpenWRT 下使用 Huawei ME909s-821 模块的 MBIM 模式接入蜂窝移动网络并使用 IPv6

Posted by

on

前言

我是远程桌面应用的重度使用者。最近,我经常需要远程到公司电脑进行办公。公司的电脑已经接入到我的分布式局域网当中,使用内部 IP 地址就能直接访问。——听起来非常美好。然而,公司的网络是对称式 NAT,且有 电信—联通 双线负载均衡,这就导致了公司网络出口一会是电信,一会是联通。我的网络大量应用了 Zerotier 二层虚拟化技术,P2P 穿透对这种场景非常敏感。为了优化线路质量,提高线路冗余度,我决定为公司路由器增加第二条互联网接入方式,这次我选择了通过蜂窝移动网络模块。

模块在网上商店可以以非常实惠的价格购入,这里我选择了 ME909s-821A 模块与 USB 转接板(含 SIM 卡槽)套餐,拿到手后,直接插入 Windows PC,可以直接使用并连接 Internet。

模块的工作模式

通过查阅资料,我发现,此类模块为了兼容多种用途,往往具有多种工作模式。如:串口,Modem,NDIS,MBIM 等等。

Huawei Module Working Mode

其中,Modem 接口是过去最常用的方法,模块本身工作为 Serial Modem,由客户端计算机执行 AT 指令,并建立 PPP 会话。

NDIS/ECM/NCM 是在 MBIM 出现之前的最优做法,模块表现为一块 USB 网卡,由模块完成网络拨号,过程对客户端计算机透明,只需让客户端计算机按照输入的 APN 等信息进行 AT(NDIS) 指令,连接成功后很快就能看到这块网卡取得 IP 地址。

MBIM 是较新的接口工作方式,是由 USB 组织官方所提供的解决方案,是完全针对上网卡环境所设计的,当我们将模块插入计算机后,Windows 10 甚至能够零配置,直接初始化使用,并能识别出 SIM 卡 ID,IMEI,以及信号强度信息。

Modem 的速度最慢,它的速度受限于串口通信,NDIS 方式 与 MBIM 方式则更加适合高速网络,尤其是 4G 网络。

尝试

首先,我尝试了 NDIS/ECM/NCM 模式。OpenWRT 有针对此模式的图形界面操作。我使用的是 OpenWRT 19.07。

opkg update
opkg install usbutils kmod-usb-net-huawei-cdc-ncm comgt-ncm luci-proto-3g luci-proto-ncm luci-proto-qmi kmod-usb-net-huawei-cdc-ncm usb-modeswitch

安装完成后,我们可以使用 lsusb, dmesg 来查看模块是否被正确识别,使用 ls -l /dev/ 看看是否存在 /dev/ttyUSB# (# 为数字)。我发现,模块已经正常驱动,但是并不存在网上资料所介绍的 wwan0 或 usb0 接口。经过测试发现,usb-modeswitch 包不应该安装,且还需要额外安装另一个包。

opkg remove usb-modeswitch
opkg install kmod-usb-net-cdc-ether

现在,我们使用 ifconfig -a 可以看到 wwan0 接口了。接下来在 Web 界面中创建接口,输入网络信息就可以了。

OpenWRT 4G using NCM

一切似乎非常美好,wwan0 获取了到了地址,设置好默认网关与跃点信息后,可以通过路由器使用蜂窝移动网络接入互联网。但是…有些不对劲。IPv6 地址去哪里了?在 Windows 系统下,我可以清楚地看到,IPv6 是正常工作的。

去年,我尝试过将 ME909s-821 模块接入到 Ubuntu 18.04 LTS 下,使用 Network Manager 接入网络,同样无法获得 IPv6 地址。查阅了很久的资料,我发现此模块似乎无法在 NCM(NDIS) 模式下使用 IPv6——即便你选择了双栈网络。通过抓包我发现,路由器在 wwan0 接口发送的 IPv6 邻居发现数据包无任何应答,也许这是一个固件 BUG?

查阅华为的模块接口手册,我们可以得知,在 Windows 8 及以上系统下,模块以 MBIM 模式工作,并且在实际尝试中能够获得 IPv6 地址。于是我决定继续尝试 MBIM 模式。

opkg remove kmod-usb-net-cdc-ether
opkg install umbim kmod-usb-net-cdc-mbim

不过,此时模块被内核默认识别为 NDIS(NCM) 模式,我们需要让内核识别为 MBIM 模式。

echo 0 > /sys/bus/usb/devices/1-2/bConfigurationValue
/bin/sleep 5
echo 3 > /sys/bus/usb/devices/1-2/bConfigurationValue

注意,上文中的 “1-2” 是模块在 USB 总线中的位置,可参考 lsusb 中的信息更改,每台设备都可能不太一样。另外,不可以直接将配置信息设置为 3,必须先置 0 以禁用设备然后再赋值,否则,后续的 umbim 将无法与模块正确通信。

然后,我们可以通过以下命令,上线 wwan0,并接入移动网络:

/sbin/ifconfig wwan0 up
/bin/sleep 5
/sbin/umbim -d /dev/cdc-wdm0 -n -t 2 subscriber
/bin/sleep 2
/sbin/umbim -d /dev/cdc-wdm0 -n -t 2 attach
/bin/sleep 2
/sbin/umbim -d /dev/cdc-wdm0 -n -t 2 connect ctnet ipv4v6

最后,在 OpenWRT 的 Web 界面中,我们创建两个 WAN,选择 wwan0 接口,协议分别是 DHCP 与 DHCPv6,就能成功地获取到双栈 IP 地址了:

OpenWRT 4G using MBIM

上述脚本我们可以加入 /etc/rc.local,让设备开机自动执行,如果可以深入研究,可以写成脚本,与 OpenWRT 集成,这样会显得更加优雅。每次插拔模块都需要切换工作模式(可以参考 OpenWRT 热插拔事件制作脚本以自动化),而每次切换都会产生不同的设备 MAC 地址,如果有相关应用依赖 wwan0 的 MAC 地址,还需要特别注意。

Hotplug 脚本(/etc/hotplug.d/usb/00-huawei.sh)

感谢评论区大佬 @Yatao Li 提供的指导,现在整理了一份 hotplug 脚本。根据需要自行调整。

#!/bin/sh

[ "$ACTION" = add -a "$DEVTYPE" = usb_device ] || exit 0

vid=$(cat /sys$DEVPATH/idVendor)
pid=$(cat /sys$DEVPATH/idProduct)
[ "$vid" = 12d1 -a "$pid" = 15c1 ] || exit 0

logger -t hotplug "me909s-821: device added"

# Disable it before switching to mbim mode...
echo 0 > /sys$DEVPATH/bConfigurationValue
/bin/sleep 5
logger -t hotplug "me909s-821: ready to switch to mbim mode..."

# Switch to mbim mode...
echo 3 > /sys$DEVPATH/bConfigurationValue
logger -t hotplug "me909s-821: switched to mbim mode(3)"


logger -t hotplug "me909s-821: bringing up wwan0..."
/sbin/ifconfig wwan0 up
/bin/sleep 5

logger -t hotplug "me909s-821: setting subscriber..."
/sbin/umbim -d /dev/cdc-wdm0 -n -t 2 subscriber
/bin/sleep 2

logger -t hotplug "me909s-821: attaching device..."
/sbin/umbim -d /dev/cdc-wdm0 -n -t 2 attach
/bin/sleep 2

/sbin/umbim -d /dev/cdc-wdm0 -n -t 2 connect ctnet ipv4v6
logger -t hotplug "me909s-821: connect command sent"

参考资料

  1. Huawei Module, USB Interface Descriptor Guide Issue 02(2015-09-09): http://download-c1.huawei.com/download/downloadCenter?downloadId=60305&version=200311&siteCode=worldwide&view=true
  2. Huawei ME906s-158 (a.k.a. HP lt4132): Linux and IPv6 support (or lack thereof): https://toreanderson.github.io/2017/07/31/huawei-me906s-hp-lt4132-linux-ipv6.html
  3. How to use 4G LTE modems like the MC7455 on both Debian/Ubuntu and OpenWRT using MBIM: https://gist.github.com/Juul/e42c5b6ec71ce11923526b36d3f1cb2c

6 responses to “OpenWRT 下使用 Huawei ME909s-821 模块的 MBIM 模式接入蜂窝移动网络并使用 IPv6”

  1. 使用这个方法可以获得ipv6的地址,但是通过ipv6 test网站测试无法使用。不知道是怎么回事。

    1. Kobayashi Kyosuke Avatar
      Kobayashi Kyosuke

      你好,抱歉回复晚了。
      如果你的设备是 OpenWRT 设备,通过本文方法获取到了 IPv6 地址后,还需要额外操作才能保证路由器下方设备以及路由器自身可以访问 IPv6 网络。
      1. 路由器自身访问 IPv6 网络:添加 IPv6 默认路由 ( ::/0 via IPv6 网关 dev wwan0 )
      2. 下挂设备访问 IPv6 网络:
      a). 方法一:手动配置 路由器通告 (参考 radvd) 并中继 wwan0 接口上的前缀地址,我没有亲自实践过。OpenWRT 自身协议栈不支持此种情况,因此必须手动配置。
      b). 方法二(简单, 但不推荐, 不符合时代发展规律):使用 NAT6。需要额外安装 OpenWRT 的 iptables nat6 支持软件包,并给局域网设备设置非 f 开头的 ULA 地址,并和 IPv4 一样对 IPv6 流量做 MASQUERADE。

      1. 作者你好,我现在使用的方案和你差不多,我现在是树莓派上用4G模块能上网,也有IPV6公网地址,现在安装了DHCP服务器,下面设备的V6地址获取是个问题了,请问你有这方面的研究吗?

        1. Kobayashi Kyosuke Avatar
          Kobayashi Kyosuke

          抱歉,暂无深入研究。不过只要复用这个 IPv6 公网地址的 /64(绝大多数情况下) 的前缀即可,同时需要配置 IPv6 路由通告功能,需要配合 radvd 还是什么的软件一起使用,或者考虑前缀的中继。这方面,可以参考 OpenWrt 的相关资料并且推荐使用 OpenWrt 的最新版本(越新的版本对 IPv6 的支持越好,并且操作越简单易懂)

  2. 东除我佬 ))

    按照文中设置成功了。
    我把拨号写在/etc/hotplug.d/usb/00-huawei.sh里:

    “`
    #!/bin/sh

    [ “$ACTION” = add -a “$DEVTYPE” = usb_device ] || exit 0

    # exit 0

    vid=$(cat /sys$DEVPATH/idVendor)
    pid=$(cat /sys$DEVPATH/idProduct)
    [ “$vid” = 12d1 -a “$pid” = 15c1 ] || exit 0

    logger -t hotplug “me909s-821a: device added”
    # Disable it before switching to mbim mode…
    echo 0 > /sys$DEVPATH/bConfigurationValue
    /bin/sleep 5
    echo 3 > /sys$DEVPATH/bConfigurationValue
    logger -t hotplug “me909s-821a: switched to mbim”
    ……
    “`

    这样就可以像手机一样热插拔了。
    另外如果有安卓共享需求,可不用删除`kmod-usb-cdc-ether`——安卓的共享使用rndis协议依赖这个。和mbim不冲突。

    1. Kobayashi Kyosuke Avatar
      Kobayashi Kyosuke

      感谢大佬深入研究!
      后续我已经放弃使用路由器直接连接模块,因为发生了不明原因的设备重启。(MT7621 方案,OpenWrt 18.06 官方原版,Kernel 4.14)
      目前未确定的原因也有很多(内核版本,硬件问题,供电问题等等)
      后续我将尝试同 SoC 方案的不同设备,并使用 21.02 最新版本(一旦 stable)再次尝试。
      再次感谢大佬的上述工作和知识分享~

Leave a Reply

Your email address will not be published. Required fields are marked *