Use USB CDC-ECM capable dongles for WWAN connection

This recipe explains how to setup and configure OpenWrt for using a USB 3G/4G/5G modem operating an USB CDC-ECM USB function supported by Linux cdc_ether driver.

The same applies to modems connected to external USB ports and internal USB-capable M.2(NGFF) or miniPCIe slots.

1. Before using your USB modem, install packages either in LuCI → System → Software or via command line:

apk update
apk add kmod-usb-net-cdc-ether

You can also add the necessary packages when building a new image with Firmware Selector.

Some [older] modems may additionally need usb-modeswitch package. It is used to switch the modem into a “working” mode. More about: USB mode switch

2. If the installation was successful, plugging the USB dongle in or restarting the internal modem will show similar messages in the log:

root@OpenWrt:~# dmesg
[  208.424433] usb 1-1: new high-speed USB device number 3 using ehci-platform
[  209.251501] usb 1-1: USB disconnect, device number 3
[  209.652469] usb 1-1: new high-speed USB device number 4 using ehci-platform
[  210.060700] cdc_ether 1-1:1.0 usb0: register 'cdc_ether' at usb-1b000000.usb-1, CDC Ethernet Device, d2:60:c8:b6:65:46

Note the interface name (usb0) mentioned on the last line, it will be used later. For another modem or different OpenWrt version the name could be eth2 or something like that.

3. It is worth to check the output of cat /sys/kernel/debug/usb/devices to make sure the necessary drivers are loaded for USB interfaces:

root@OpenWrt:~# cat /sys/kernel/debug/usb/devices

[...]

T:  Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  3 Spd=480  MxCh= 0
D:  Ver= 2.00 Cls=02(comm.) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=12d1 ProdID=14dc Rev= 1.02
S:  Manufacturer=HUAWEI
S:  Product=HUAWEI Mobile
C:* #Ifs= 3 Cfg#= 1 Atr=80 MxPwr=500mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=06 Prot=00 Driver=cdc_ether
E:  Ad=83(I) Atr=03(Int.) MxPS=  16 Ivl=32ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=cdc_ether
E:  Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#= 2 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=(none)
E:  Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=125us

[...]

Some modems require manual switching into ECM mode by using AT commands. This could be done on any computer prior to installation or on the router directly using a terminal application like picocom. More about: sending AT commands from the router.

1. A few extra packages need to be installed in order to “talk” with the modem from the router:

apk update
apk add picocom kmod-usb-serial-option

2. Connecting to the Quectel Modem using picocom:

picocom /dev/ttyUSB2

Note: To exit picocom, hold down the CTRL key. While holding it, press A, then press X.

3. This is an example for popular Quectel modems (do not expect these proprietary commands to work on devices from other manufacturers):

AT+QCFG="usbnet"	# Check the current mode
AT+QCFG="usbnet",1	# Set ECM mode

4. Reset the modem to apply changes: unplug and replug it, or send the command:

AT+CFUN=1,1

5. It is worth checking the APN(s) configured on the modem. If the modem offers its own web interface, use it for this task. Alternatively, if the modem has serial (ttyUSB) interface(s) exposed, use a terminal program to query the modem with AT+CGDCONT? and observe the output. Example:

AT+CGDCONT?
+CGDCONT: 1,"IPV4V6","internet",...
+CGDCONT: 2,"IPV4V6","ims",...
+CGDCONT: 3,"IPV4V6","sos",...

6. Typically, but not always, context #1 is used for Internet connection. If it is not configured with the correct information (IP type and APN), it is recommended to set the desired parameters. Example:

AT+CGDCONT=1,"IPV4V6","internet"

If necessary, replace IPV4V6 (for IPv4 and IPv6) with IP (for IPv4 only) or IPV6 (for IPv6 only), and use your carrier APN instead of internet.

7. While in the terminal, check the modem firmware version with ATI and see if there is an upgrade available.

8. Reset the modem to apply changes: unplug and replug it, or send the command:

AT+CFUN=1,1

:!: Since ECM modem typically behaves like a router with DHCP and NAT, it is important that OpenWrt is LAN IP subnet is different from the modem is IP subnet. For some modems the default IP address is 192.168.1.1, which clashes with OpenWrt is default. Therefore if that address conflict cannot be resolved on the modem side, then OpenWrt LAN IP subnet should be changed to something else.

1. Add new IPv4 and IPv6 network interfaces:

# Add WWAN interface (IPv4)
uci -q del network.wwan
uci set network.wwan=interface
uci set network.wwan.proto="dhcp"
uci set network.wwan.device="usb0"
# Assign "wwan" interface to the WAN firewall zone
uci del_list firewall.@zone[1].network="wwan"
uci add_list firewall.@zone[1].network="wwan"
 
# Add WWAN6 interface (IPv6)
uci -q del network.wwan6
uci set network.wwan6=interface
uci set network.wwan6.proto="dhcpv6"
uci set network.wwan6.device="usb0"
uci set network.wwan6.extendprefix="1"
# Disable "IPv6 source routing" to prevent ISP IPv6 leaks when using a VPN
uci set network.wwan6.sourcefilter="0"
# Assign "wwan6" interface to the WAN firewall zone and enable IPv6 masquerading
uci del_list firewall.@zone[1].network="wwan6"
uci add_list firewall.@zone[1].network="wwan6"
uci set firewall.@zone[1].masq6="1"
 
# Save changes and restart services
uci commit
service network restart; service firewall restart

2. Configure custom TTL and Hop Limit to bypass carrier tethering restrictions:

# Define custom TTL/Hop Limit values and specify network devices to bypass tethering restrictions
# - Use 64 for modems in QMI/MBIM mode (Direct Mode)
# - Use 65 for tethered phones and modems in ECM/RNDIS mode (Hostless Mode)
WAN_TTL="65"
WAN_HLIM="65"
WAN_DEV="eth1, ppp*, usb*, wwan*"
 
# Create the custom nftables rules file
cat << EOF > /etc/nftables.d/custom-ttl-and-hlim-rules
oifname { $WAN_DEV } counter ip ttl set $WAN_TTL comment "IPv4: Bypass tethering"
oifname { $WAN_DEV } meta l4proto != ipv6-icmp counter ip6 hoplimit set $WAN_HLIM comment "IPv6: Bypass tethering (excluding ICMPv6)"
EOF
 
# Include custom nftables rules file in firewall config
uci -q del firewall.custom_ttl_and_hlim
uci set firewall.custom_ttl_and_hlim="include"
uci set firewall.custom_ttl_and_hlim.enabled="1"
uci set firewall.custom_ttl_and_hlim.type="nftables"
uci set firewall.custom_ttl_and_hlim.path="/etc/nftables.d/custom-ttl-and-hlim-rules"
uci set firewall.custom_ttl_and_hlim.position="chain-post"
uci set firewall.custom_ttl_and_hlim.chain="mangle_postrouting"
uci commit firewall
 
# Reload the firewall to apply changes
fw4 reload

For documentation, please see:

Note: For the IPv6 connection to work, enable “IPv6 Masquerading” in the WAN zone under the Firewall section. Additionally, you can optionally disable “IPv6 source routing” (also known as IPv6 source filter) on the wan6 and wwan6 interfaces when using a VPN to prevent IPv6 leaks from your ISP:

1. Navigate to Network → Interfaces → Add new interface... → Protocol: DHCP Client, Interface: “usb0” (or another name found earlier)

2. Assign the firewall zone (wan) on 'Firewall Settings' tab.

3. Open Advanced Settings and make sure that both “Use default gateway” and “Use DNS servers advertised by peer” checkboxes are ticked.

Alternatively you can edit the configuration files with any text editor like vi or nano:

1. Add new IPv4 and IPv6 network interfaces in /etc/config/network:

config interface 'wwan'
	option proto 'dhcp'
	option device 'usb0'
 
config interface 'wwan6'
	option proto 'dhcpv6'
	option device 'usb0'
	option extendprefix '1'
	# Disable "IPv6 source routing" to prevent ISP IPv6 leaks when using a VPN
	option sourcefilter '0'

Other DHCP and DHCPv6 options can also be used here.

2. Add the same IPv4 and IPv6 network interface names to the “wan” firewall zone and enable IPv6 masquerading in /etc/config/firewall:

config zone
	option name 'wan'
	[...]
	list network 'wwan'
	list network 'wwan6'
	option masq6 '1'

3. Restart the services:

service network restart; service firewall restart

Verify domain name resolution with nslookup:

nslookup openwrt.org localhost

IPv6 Test:

For some modems adding an interface will be sufficient, but others may need an APN provisioned, it is also sometimes necessary to send a special “autodial” command to the AT command port. It is recommended to install additional packages picocom kmod-usb-serial-option and consult AT Commands Guide for the given modem.

If the modem needs a “dial” command sent on each connection attempt, then it is worth trying to configure the comgt package. For instance, Sierra Wireless modems using the so called DirectIP (DIP) mode can be used setting up the comgt-directip package (for which there is no current luci-proto-* support). A similar support exists for some modems using the NCM interface instead (via comgt-ncm + luci-proto-ncm). If your modem does also have an NCM interface (nut no MBIM/QMI) it is best to switch from ECM to NCM to get full luci support, otherwise install the base comgt package and get inspired by comgt-ncm to implement the same for your ECM dongle.

Compared to PPP or QMI protocols there are no settings provided from OpenWrt for the modem. All the configuration changes are made on the modem itself, typically by using AT commands.

Alternatively, some manufacturers (Huawei, ZTE, etc) provide a web interface where you can enter your APN, check connection status, enter PIN code, enable data roaming, change bands, send/receive SMS, etc. As an example, with Huawei modem in HiLink mode the interface is accessible via http://hi.link or http://192.168.8.1 (that is a default IP address). Modem is own IP address can be seen in the System Log:

daemon.notice netifd: wwan (20573): udhcpc: broadcasting discover
daemon.notice netifd: wwan (20573): udhcpc: broadcasting select for 192.168.8.198, server 192.168.8.1
daemon.notice netifd: wwan (20573): udhcpc: lease of 192.168.8.198 obtained from 192.168.8.1, lease time 43200
daemon.notice netifd: Interface 'wwan' is now up

If access to the modem interface is blocked, it may be that your firewall does not allow it. In this case you can define a rule like the following:

config rule
	option name 'Allow-HiLink'
	option src 'lan'
	option proto 'tcp'
	option target 'ACCEPT'
	option family 'ipv4'
	option dest 'wan'
	list dest_ip '192.168.8.1'
  • Last modified: 2026/09/06 01:02
  • by lastedit