E3372 stick + OpenWrt + USSD
by kacang bawang
This post is about setting up a LTE/4G/3G (cellular) modem to work with OpenWrt. But not just work, to also be able to use USSD codes and read SMS in order to check account balance and refill the data quota (data plan).
I chose E3372 for my modem because it has a large user base, and is supported by OpenWrt. The modem comes in several flavors, which can be identified from the serial number.
1 2 3 |
`E3372x-yyy` x = `h` or `s`, this is the hardware version, `h` = hilink, `s` = stick `yyy` = region code, `153` = europe, `607` = asia (there are a couple of others, stay away from 320) |
At first I was attracted to the hilink
firmware because it offers a nice web interface through which the modem can be controlled, and tasks such as dialing USSD codes to buy new data plans can be accomplished. Furthermore, if you use a modified WebUI
it unlocks some hidden features of the modem, such as the ability to change IMEI and fix TTL. The stick
firmware can also do all this, but I did not know this yet.
Checking the current firmware.
Initially, you should have the modem be recognized by the system and a new interface should appear 192.168.8.100
. The modem itself will be at 192.168.8.1
. You can check the current firmware version on a hilink
firmware with this script
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#!/bin/sh MODEM_IP="192.168.8.1" curl -s -X GET "http://$MODEM_IP/api/webserver/SesTokInfo" > /tmp/ses_tok.xml COOKIE=`grep "SessionID=" /tmp/ses_tok.xml | cut -b 10-147` TOKEN=`grep "TokInfo" /tmp/ses_tok.xml | cut -b 10-41` curl -s -X GET "http://$MODEM_IP/api/device/information" \ -H "Cookie: $COOKIE" -H "__RequestVerificationToken: $TOKEN" \ -H "Content-Type: text/xml" # in case of broken MTD16 (data) partition, will print out error 100002 curl -s -X GET "http://$MODEM_IP/api/dialup/profiles" \ -H "Cookie: $COOKIE" -H "__RequestVerificationToken: $TOKEN" \ -H "Content-Type: text/xml" |
Flashing
The firmware, which can itself be stick
or hilink
, must match the above model number.
Frequently, if you buy it online, the modem will come already unlocked (this was my case), and all you have to do is flash it with a firmware of your choice. The biggest resource for firmwares is here, albeit it does not have any -607
firmwares. The latter can be found here.
There is also the WebUI
, which is the web server that runs on the modem and, if modified, allows for some cool features. The WebUI
is common between -153
and -607
modem versions.
With an unlocked modem all you need to do is put the modem into debug mode:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
debug_mode.xml: <?xml version="1.0" encoding="UTF-8" ?> <api version="1.0"> <header> <function>switchMode</function> </header> <body> <request> <switchType>1</switchType> </request> </body> </api> curl -X POST -d @debug_mode.xml http://192.168.8.1/CGI |
Modem will reboot and now be accessible over /dev/ttyUSB0..6. The 0 device will now accept AT
commands, which we will use to put it into flashing mode. The ethernet interface may or may not still be there, and it may or may not have ip.
How to send AT commands.
1 2 3 4 5 |
#connect to the modem like this socat - /dev/ttyUSB0,crnl #then do AT^GODLOAD |
Modem will again reset, no interface will be visible in ifconfig
and it will not respond to AT
commands, only /dev/ttyUSB0
will be visible.
Now use balong-flash
from here to flash the firmware.
1 2 3 |
#defaults to /dev/ttyUSB0 (else -pX), -k means do not reboot so we can flash webui after this balongflash -k .bin balongflash .exe |
De-Bricking / The Needle Method
In my quest, I had mistakenly flashed a -153
firmware to a -607
device, which ended up soft-bricking it. The modem would boot, but had no /dev/ttyUSB
devices to show and its ethernet interface did not come up (nothing at 192.168.8.1). So, this is a good time to talk about recovery and de-bricking.
Great Thanks go out to forth32
for both the balongflash
utility and the balong-usbdload
utility which we are about to use. Your tools have saved many modems (and their owners) from despair!
Here is the needle method. Watch this video.
1 2 3 4 5 6 |
#boot with external bootloader. If ttyUSB0 does not work, try ttyUSB1,2 balong-usbdload -p /dev/ttyUSB0 usblsafe-3372h.bin #then can flash as usual balong_flash -k firmware-607.BIN balong_flash webui.exe |
This gave me a working E3372h-607 in hilink
mode, with a modified firmware and a modified WebUI
.
Hilink Mode
There is one more thing that needs to be done in order to activate the hidden functions. If you click on some items in the menu it will offer to run “WebUI Init”, which is nothing but a shell script, which I included below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
... #connect to the modem with adb adb connect $ip:5555 #remount /system as read-write adb shell mount -o remount,rw /system /system #delete any lines that have "webui_init.sh" from autorun.sh adb shell "busybox sed -i '/webui_init.sh/d' /system/etc/autorun.sh" #add the line to call "webui_init.sh" to autorun. webui_init.sh is already present on the device. adb shell "busybox echo -e '\n/app/webroot/webui_init.sh' >> /system/etc/autorun.sh" #remount system back to read-only adb shell mount -o remount,ro /system /system ... |
webui_init.sh
itself makes a bunch of symbolic links in /usr
or /bin
(I don’t remember now) to binaries and scripts in /app/webroot/
. These binaries and scripts are what allows the special functions.
Now if you go back to the web interface it will have a big sign that says that some corruption has been detected and you need to do a factory reset. Do not worry, it will not undo what the webui_init
script had achieved. After rebooting, the device is ready to go.
Why I did not like the Hilink mode.
Slick web interface, adb, what’s not to like? Well… First there is the double NAT. Its impact can be diminished by using DMZ, but the modem will still be there, still listening on the external ip. Which brings me to my next point…
The modem is quite open! adb
, telnet
and the web interface are listening on 0.0.0.0
, further, there is second web server that appears after the webui_init
activation on port 5080. That is busybox serving up a cgi-bin
folder with shell scripts, again, on 0.0.0.0
. And then, there’s some funny busyness going on with dns listening on 10.34.24.69
, which is an ip that is not bound to the modem. Take a look for yourself:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
root@android:/app/webroot # netstat -ltupn Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.0.1:5037 0.0.0.0:* LISTEN 197/adbd tcp 0 0 0.0.0.0:5555 0.0.0.0:* LISTEN 197/adbd tcp 0 0 0.0.0.0:53 0.0.0.0:* LISTEN 3309/dns tcp 0 0 :::80 :::* LISTEN 246/webserver tcp 0 0 :::23 :::* LISTEN 196/busybox tcp 0 0 :::5080 :::* LISTEN 218/busybox udp 0 0 0.0.0.0:53 0.0.0.0:* 3309/dns udp 0 0 127.0.0.1:53 0.0.0.0:* 3309/dns udp 0 0 0.0.0.0:67 0.0.0.0:* 761/dhcps.real udp 0 0 10.34.24.69:60317 0.0.0.0:* 3309/dns udp 0 0 10.34.24.69:51631 0.0.0.0:* 3309/dns udp 0 0 :::547 :::* 788/dhcp6s udp 0 0 :::53 :::* 3309/dns udp 0 0 ::1:53 :::* 3309/dns |
There is a firewall, but that still leaves the LAN. It would take some time to track where all of this is coming from and clean/password it up in such a way that I, myself, would still be able to use it. However, there is an easier way.
Changing to Stick Firmware
In stick mode, the modem would not have its own ip, it would relay the cellular data to/from the ip on the router. Thus, it would be the router facing the world, not the modem. This arrangement is much preferred as there is no double NAT, and it is a whole lot easier to control what goes on my OpenWrt router than a 3rd party android device.
To change over to the stick
firmware (on hilink
hardware) we merely need to re-flash it. I grabbed a copy of the non-hilink
607 firmware from the Austrian forum and flashed it. Same as before: debug mode
, at^godload
, balongflash firmware.bin
.
There is no UI for stick firmware under linux. This presents a problem, how will I be able to run USSD codes to buy new data, or read/send SMS? Fortunately there is nifty tool that does just that, but let’s configure the modem first.
We will configure in NCM mode, which is supposed to give the best throughput (up to 30-50 mbps). Good info here. The configuration will depend on the port settings of the modem, lets review those first.
Best ports explanation here. Additional info here and here.
By default, my stick firmware was set with the following port config:
1 2 3 4 |
AT^SETPORT? ^SETPORT:A1,A2;12,1,16,A1,A2 OK |
This means to boot to cd-rom drive + flash drive initially and upon mode switch to become a 3g modem with the flash and cd-rom still available. The important part here is the 3g modem choice. In order to make this one work, you have to choose /dev/ttyUSB0
as the option device
, choosing /dev/cdc-wmd0
will not work, as the device will not respond to AT
commands on that device, and you will see the following log output:
1 2 3 4 5 6 7 8 9 10 |
daemon.notice netifd: wan (6693): Timeout running AT-command daemon.notice netifd: wan (6693): Failed to set operating mode daemon.notice netifd: wan (7490): Stopping network wan daemon.notice netifd: wan (7490): sending -> daemon.notice netifd: Interface 'wan' is now down daemon.notice netifd: Interface 'wan' is setting up now daemon.notice netifd: wan (7499): Configuring modem daemon.notice netifd: wan (7499): WARNING: Variable 'modes' does not exist or is not an array/object daemon.notice netifd: wan (7499): Setting mode daemon.notice netifd: wan (7499): sending -> |
Here is a working network config for this port setting:
1 2 3 4 5 6 7 8 |
config interface 'wan' option ifname 'wwan0' option proto 'ncm' option device '/dev/ttyUSB0' option mode 'auto' option apn 'the_text_name_of_your_mobile_network' option ipv6 'auto' option metric '100' |
If you connect to /dev/ttyUSB0
and you will be able to see periodic updates about the network that you are on and the signal strength (RSSI). For me, despite having chosen 3G, the network reports as LTE.
1 2 3 4 5 6 7 |
^RSSI:31 ^HCSQ:"LTE",72,66,196,28 ^RSSI:31 ^HCSQ:"LTE",72,66,206,28 |
This works, however, the use of /dev/cdc-wdm0
device is supposed to achieve better performance than /dev/ttyUSB*
. (Unfortunately, I was unable to test it, as my cell provider caps out at about 12Mbps). Here is what you need to achieve that. First, configure the ports as follows:
1 2 3 |
AT^SETPORT="FF;10,12,16" OK |
The extraneous cd-rom and flash drive have been removed, and we then choose 4G modem + NCM (+ always need PCUI). Very clean and minimized. After this port reconfig, the device will do AT
commands on /dev/cdc-wdm0
and the following OpenWrt configuration will work:
1 2 3 4 5 6 7 8 |
config interface 'wan' option ifname 'wwan0' option proto 'ncm' option device '/dev/cdc-wdm0' option mode 'auto' option apn 'the_text_name_of_your_mobile_network' option ipv6 'auto' option metric '100' |
USSD and SMS
In order to use USSD codes and SMS messages, we will need sms-tool
and luci-app-sms-tools
. Big Thanks go out to cezary
and IceG
. Install instructions here.
Once running, you can send SMS messages with send
and recv
commands, as well as navigate USSD menus with ussd
command. Here is an example of how to navigate a USSD menu:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
root@OpenWrt:~# sms_tool -d /dev/ttyUSB0 ussd "*123#" Choose option 1.Check balance 2.Buy quota 3.Transfer balance root@OpenWrt:~# sms_tool -d /dev/ttyUSB0 ussd "2" Choose option 1.1Gb 2.2Gb 3.3Gb root@OpenWrt:~# sms_tool -d /dev/ttyUSB0 ussd "3" Success! SMS sent |
The remote actually maintains a state of where you are in the menu, so you just send more USSD commands to navigate it.
If you installed the Luci app, you will be able to do the same thing through the web interface. Nice, huh?
So that’s pretty much it, we’ve installed the modem and are able to top up our quota. Have fun surfing. Hopefully your provider doesn’t cap the speed as tightly as mine, heh.
PS. Some links about the available AT
commands for these modems:
https://routerunlock.com/useful-at-commands-for-huawei-modem/
https://gist.github.com/artizirk/20acc2ab07fe6cad9fcc