Inside the ZTE MF823 4G Dongle

A year ago, I built a Raspberry Pi based car computer to provide music, along with weather, location and speed information, while going on a road trip around Australia. At the start of the trip, the computer used an external USB Huawei K3715 3G Dongle for Internet connectivity.

The system acts as wifi access point for other devices in the car.  Using the on board wifi adapter provided with the Raspberry Pi 3.

As the trip progressed though I started to get tire of suffering 3G speeds in the age of 4G networks. My other complaint was the overall quality of the network connection.

I have a large external 4G antenna mounted on the bullbar of the car with the aim of improving the connection qualit in rural areas. The Huawei K3715 does not support an external antenna connector, forcing the use of a 3G induction pad to have the two work together.

While shopping around for an upgrade, I was told that Telstra ( Australia’s incumbent telco ) had recently discontinued 4G dongles. Apparently as they suffer compatibility issues with Windows 10, so I would need to either get a standalone modem hot spot or find somewhere carrying old stock.

Since the device is used in a car , switching to a standalone unit would also add the challenge of getting the device to work with a 12 volt power source. Not wanting introduce more headaches, I headed down to the local post office and was able to pick up a Telstra branded ZTE MF823 off the shelf for $39.

ZTE MF832 4G Dongle
While the device offers 4G support and provides not one but two external antenna ports. My initial impressions of the device after plugging it in were not great.

It appears on the host system as a virtual Ethernet adapter with the user controlling the device through a web interface. I hate this approach as so many manufacturers ship their products with woeful interfaces. While going to great length to hide all the great capabilities of the hardware itself.

But first impressions can be deceiving;  after a bit of time poking around the ZTE MF823, my opinion was completely turned around.

Performing a quick port scan against the dongle with nmap told me open three ports were listening on the device:


23/tcp open  telnet
53/tcp open  domain
80/tcp open  http

Port 80 & 23 were expected but telnet made things interesting. After some research, I found these devices ship with a default password ‘zte9x15‘ and run BusyBox.

Logging via telnet:

Login: root
Pwd: zte9x15

Logging into the ZTE MF832 via telnet
Looking at the results of /proc/cpuinfo, df -h and top. I discovered out the ZTE MF823 is just a standalone ARM v7 based Linux system with a 64mb file system.

ZTE MF832 Linux Top Command

Poking around the file system, I found most of the content that matters resides under the /usr/zte_web/web directory. With the HTML and Javascript located in this directory providing the web based user interface that is served up on port 80.

The quality of the code itself for the interface is not too bad either, built with KockoutJS and jQuery.

Some areas of note:

  • /usr/zte_web/web/tmpl Contains a bunch of template files for the web interface. Not so interesting in itself but ZTE must reuse this code base over a number of the devices they make. This directory contains templates for managing a wifi access point, and other features that the ZTE MF823 does not support.
  • /usr/zte_web/web/js/config/datacard/mf823/config.js Continuing along from the point above, this config file in this director allows the features for a device to be set. This gives ZTE control of the functionality made available to the end user in the web management interface.
  • /usr/zte_web/web/js/config/datacard/mf823/menus.js Controls what functionality menus are shown on the admin pages.
  • /usr/zte_web/web/MF823_Help Contains the user manual in HTML format, the code seems to have come from Microsoft Word so don’t bother looking at the code. Once seen, you cannot unsee HTML that bad 🙁
  • /usr/zte_web/web/zte_log This directory is full of log files, useful for debugging any connection issues
  • js/main.js Line 1 has a flag window.zte_web_ui_is_test = false, changing this to true enables a debug mode in the interface. Displaying a 2G network connection and displaying 20 odd test SMS messages in the inbox.

Setting The Time

When the system first boots, due to the lack of a hardware real time clock.  The time and date will automatically default to Sun Apr  1 00:00:00 UTC 2012.

Not really a huge deal. But if the dongle is going to be constantly powered up, its probably a good idea to set the time with ntpd. This will make the debugging of logs etc a lot easier if issues are encountered at a later date.

ntpd -p

Changing The IP Range

From the factory the device ships using the address space. This can can cause issues in networks where the subnet is already being used.

In my case the car computer communicates with devices connecting over wifi on that subnet so the dongle was going to have to change.

Luckily ZTE has already added the functionality to change the device IP and DHCP range. They just decided to hide it from to the end user.

To enable the IP management page edit /usr/zte_web/web/js/config/datacard/mf823/config.js with vi

Go down to line 177 just below the section talking about PIN management and paste in the following code:


Save the file, and then reload the admin interface in your browser. If you click on the “Settings”, expand the “Device Settings” heading on the left hand side of the page.

You will now see a menu labeled router settings,  click on the new menu item to bring up a page allowing you to change the IP of the device and subnet the DHCP service hands out leases on.

These fields are read only while the device is connected to a mobile network. So if the fields appear grey and you cannot change the values. Go back to the home page of the device and click the disconnect button. Upon returning to the router settings page you will now be able to change the settings.

Once you have changed the values click the save button. Then simple take the dongle out and plug it back in to have the changes take effect.

Removing the Telstra ( Or other Telco ) Branding

I have to come to love the device but I still didn’t want Telstra branding staring me in the face every time I use the device. So, time to make some interface customisations of my own.

If you decide to follow in my footsteps, before you get started it may pay to make a backup of the html and image files you are going to change. On my device there is 25mb free in the /usr partition that can be used for storage just in case you want to revert the changes later.

ZTE MF832 covered with Telstra Branding

The main large image on the right hand side on the home page in the device administration interface is defined on line 82 of  /usr/zte_web/web/tmpl/home.html if you want simply delete the line and your done.

In my case I wanted to replace it with something else so I simply found an image I wanted, used the python SimpleHTTPServer module to start a web server instance for the image location on the host machine the USB stick was plugged into i.e

python -m SimpleHTTPServer

In the telnet session on the USB dongle, use wget to pull the new imagery across from the host i.e


Start the Python Simplehttpserver module

With the logo / banner located up the top of page in the header of the administration section you can either delete the file zte_logo.png and import your own logo for the space using the same process as before or edit the index.html file:

vi index.html

Delete line 28 then save the changes. Reload and the interface will display without the Telstra logo up the top.

The finished admin page without branding

Unlock from the Telstra network:

After two calls to Telstra support and a week waiting for them to activate my data SIM. I decided to give up on them activating the service completely.

The path of least resistance would be to just throw their SIM card in the bin. Then focus my energy on unlocking the dongle so it could be used on another network instead.

I brought an unlock code for the device from for $10 USD, which worked. A small price to pay to avoid wasting more time dealing with the Telstra customer support team.

You may also be able to use this on-line tool to unlock the device as it generates code for free. I didn’t find this too until after I had the device unlocked. So I haven’t been able to test the service personally though.

Moving Forward

Since the administration interface is all written in HTML and Javascript. If you open up developer tools in your browser while looking at the management area, you will see a bunch of AJAX calls being fired off to get data for the front end.

You can simply alter the queries, giving you a simple API that you to can use build your own front end. This could be very handy for monitoring data usage or signal strength if the device is being used in an IOT type environment.

For example the calls from the front end are made to the endpoint below:

With the cmd parameter just being a bunch of parameters you want to receive information back about. The main interesting ones are:

  • signalbar
  • network_type
  • network_provider
  • modem_main_state
  • total_tx_bytes
  • total_rx_bytes

urlencode the ones you would like to receive information about and then add them to the cmd parameter like this:

This will return a JSON object containing the values for the parameters requested.


From here it is just a case of writing so code to parse the JSON values and display or store as you see fit.

Further Reading:

4 thoughts on “Inside the ZTE MF823 4G Dongle

  1. Sam

    Excellent article! Ended up using the “Changing The IP Range” section to add the Router Settings menu 🙂

    Just an updated – you need to go to menu.js not config.js to make the changes in that section 😉

    Thanks for posting this, it’s awesome!

  2. Tobias

    With my version of the ZTE MF823 (HW: MF823-1.0.0 and Software: WEB_MIRCOPGBRMF823V1.0.0B02) it was a bit more tricky to read the json parameters from the device.
    In my case I had to:
    – add the parameter “_”:”current UnixTimestamp” (in Microseconds)
    – set the referer header in the http request to “”

    Otherwise the values in the json response were empty.

  3. P4

    I was hanging around on my MF823 shell and accidentally found this very interesting line in /usr/zte_web/web/zte_log/zte_syslog.log (ignore quotation mark of >, please):

    > Sun Apr 1 00:45:03 2012 zte_topsw_syslog.c 62 send data begin send_ip = port = 514

    Does your MF823 also send syslog messages to some strange host, in my case located in foreign AS2119 (I am connecting from Poland and not Sweden) or you didn’t noticed that? Grepping zte_syslog.log for send_ip should be pretty accurate.

    I can see 78 hits already and considering to blackhole this host since next lines in this syslog includes my IMEI, IMSI and other sensitive data. 🙁

Leave a Reply

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