Build a 5G modem for backup uplink
I got a pretty inexpensive cellular data plan last year, that has unlimited data, along with a crappy tablet. No, I don’t name names, but if you do care about those things, it is trivally easy to figure out what I am talking about.
It works generally great, and I tried to put that onto my old Huawei E3372 stick to make it serve as a secondary uplink of my router. However, due to the band limitation of the hardware (and I do have the most compatible submodel of E3372 - I have an E3372-510), that cellular plan will not get any 4G signals, while the other 2 carriers work just fine. At best you’ll get 3G signal that behaves like GPRS, and more than likely AT+COPS=? won’t show that particular carrier at all. This won’t work.
So what’s the hottest alternative out there? It appears that Quectel RM520N-GL has a pretty large user community, and widely utilized by both eastablished manufacturers (e.g., GL-inet) and some new ones (like ZBT), as well as home-craft 5G boxes (for instance, Waveshare). You can also find the module and various enclosures on Aliexpress too. So that’s what I did, grab a module and an enclosure there, largely inspired by a GitHub repo. And here the journey started.
Let’s revisit my goal here: I want a 5G modem, with reduced cost, that either runs openwrt on its own since that’s everything else my network infra uses, or simply passthrough the IP it received from the carrier to my router, as few NAT as possible. No other features like Wifi are needed. The first one ruled out those GL-inet routers. While I believe they’ll work (and work great), $350-400 is a bit on the too much side. You can get ZBT routers that does 5G and Wifi from Aliexpress for ~$300+, but again, I don’t need another Wifi, plus the box looks huge and ugly. So I decided to go with just a module and a small box that does the job.
First thing is the module - everyone says RM520N-GL, and that does cover a decent amount of bands globally, including the US. If you take a look at Waveshare Wiki, that pretty much covers every band you can think of.
But… very few places would mention you that there are at least 2 submodels of RM520-GL - there are RM520NGLAA and RM520NGLAP. And when you see there are many ~$60-$70 RM520N-GL modules on Aliexpress, while there are also ones ~$140, that’s exactly why. What’s the difference? GLAA supports both USB and PCIe interface, while GLAP only does PCIe. And no, it’s not something software, but hardware. You can’t fix it yourself, at least I can’t find a way to. If you do plan to use something like a “5G M.2 to RJ-45 Kit”, or the enclosure I use, it has to be GLAA. Maybe you can do the GLAP with a RPi5, I don’t know.
Secondly, the enclosure. The Github repo I mentioned above does recommend an enclosure that you can get from rework network, I got the exact same model from Aliexpress, though it appears I got the last one in stock. Rework network says it will be restocked by 9/10. It the same price on Aliexpress.
I can’t say the box is built with super good quality - for example, the aluminum block that serves as the base for 5G module, the screw hole for holding the module in place, is not perfectly aligning with the slot of the module. But it still does the job. Another caveat is that, while the box supports PoE, it DOES NOT support active PoE 802.3af. I found it out later that realtek-poe running on my Zyxel switch won’t power it on. But, a USB cable seems powering the thing as happily, so I am not too concerned about that either. Thirdly, the pigtail antennas provided in the kit seems a bit on the too long side, that the antennas I bought cannot fully cover the threads. That might explain why I got a less-than-ideal signal, but it could also possbly be that my 5G modem is placed in the closet right in the center of my basement, so I can’t tell. I don’t know what antenna could cover the threads perfectly.
Putting those parts together is not too complicated, but the enclosure does not come with any manual. You’ll need to rely on the pictures on the website to figure out how to assemble it. Once assembled, plug that thing onto openwrt box, and install the packages on openwrt side, following the guide here:
root@openwrt:~# opkg update && opkg install kmod-usb-net-cdc-ether kmod-usb-serial-option socat
after that you should be able to find several serial interfaces under /dev
:
root@openwrt:~# ls -alh /dev/ttyUSB*
crw-rw---- 1 root dialout 188, 0 Sep 7 10:38 /dev/ttyUSB0
crw-rw---- 1 root dialout 188, 1 Sep 7 10:38 /dev/ttyUSB1
crw-rw---- 1 root dialout 188, 2 Sep 7 10:38 /dev/ttyUSB2
crw-rw---- 1 root dialout 188, 3 Sep 7 10:38 /dev/ttyUSB3
In my case, ttyUSB2
is the AT command interface, YMMV. Just try each one out if USB2 is not, it won’t hurt. Use socat /dev/ttyUSB2,b115200,echo=0,crnl -
to talk to the modem, start with ATI
, you should see something like:
Quectel
RM520N-GL
Revision: RM520NGLAAR03A04M4G
Then follow the initial setup steps on the Github guide, namely:
AT+QCFG="data_interface",0,0
AT+QETH="eth_driver","r8125",1
AT+QCFG="pcie/mode",1
AT+QCFG="usbnet",1
AT+QMAPWAC=1
AT+CGDCONT=1,"IPV4V6","apn-here-inside-of-quotes"
AT+QPRTPARA=1
AT+CFUN=1,1
Those commands will set up the modem to use both PCIe and USB for data and diag, enabling the ethernet port (people claims it’s a 2.5Gbps port on the enclosure I use, but I can’t test), enable ECM mode (if you only want a USB cable for both power and data, like I do), enable auto dial and set APN of your carrier. I replaced IPV4V6
with IP
since there is no too much of a point to have a secondary IPv6 uplink there for me, but feel free to otherwise.
You don’t need to run the scripts provided by that repo if you don’t want a WebUI (simpleadmin) on the module, or you just need TTL changed.
After that, create a new interface on openwrt, name it like wwan
, and have the device point to usb0
- if not exists, check what dmesg
says. You should see a NAT’ed address in the space of 192.168.225.0/24
, which is the default DHCP pool provided by the modem. Now we will set up IP Passthrough, so that the IP received from the carrier will directly appear on the openwrt interface. The fewer NAT, the better.
Use socat
again to send AT commands:
AT+QMAP="MPDN_rule",0,1,0,3,1,"FF:FF:FF:FF:FF:FF"
AT+QMAP="IPPT_NAT",0
The explanations of those numbers are available on the GitHub repo as well. The only difference is that 3
- that bit stands for the IPPT (IP Passthrough) mode. 1 - ethernet, 2 - Wifi, 3 - USB, 4 - any devices, 5 - nic2. I am using USB here instead of ethernet, so I use 3
instead of 1
here. The second command supposedly completely disables NAT. If you don’t run the 2nd one, you’ll still get carrier IP on the openwrt interface, but if you do traceroute, you’ll see it still flows through 192.168.225.1
. Running the 1st and 2nd command will both temporarily shut down the USB connection for a sec, and in that sense, socat
will automatically exit. Don’t be panic.
Also, getting carrier IP not necessarily means you’ll have a public IP. At least not with my cellular carrier. Sometimes I got a DoD IP, sometimes within CGNAT range, but never real public IP.
Now the modem will access the Internet properly, try something like a ping -4 -c3 -I usb0 1.1.1.1
or curl --interface usb0 https://ipinfo.io
, by which they should both work.
If the carrier sets quota on hotspot data, but unlimited for tablet use itself, you might want to change IMEI and set outgoing TTL to “masquerade” your traffic. I am no lawyer; when in doubt, don’t act. To change the IMEI, use socat to access the AT command interface, and backup current IMEI first:
AT+GSN
123456789012345
then change it to tablet IMEI:
AT+EGMR=1,7,"new imei"
reboot using AT+CFUN=1,1
, then run AT+GSN
again to check whether it persists.
To change outgoing TTL, assuming using openwrt 21+ (which uses nftables), put the following in /etc/firewall.users
:
nft add rule inet fw4 mangle_postrouting oifname usb0 ip ttl set 65
nft add rule inet fw4 mangle_postrouting oifname usb0 ip6 hoplimit set 65
So far there is one bug I noticed with IPPT, that if the modem is rebooted, the openwrt interface will still have a 192.168.225.x
IP. Restarting the openwrt interface however, gets the IP from the carrier.
openwrt can also use adb
to access the shell of the module, as well as updating firmware using qfirehose
. Both are available from openwrt repo. To update the firmware, download the latest firmware from Internet, put in /tmp
, unzip it to a directory say /tmp/firmware
, then just run
qfirehose -f /tmp/firmware
After updating you might need to re-run
AT+QMAPWAC=1
AT+CFUN=1,1
if you found the modem is no longer in ECM mode.