Building a SMS gateway from a Huawei USB Modem

In this tutorial, we will use a cheap usb modem to send SMS messages over the internet. We can use both a gui and an API for interactive and scripted uses

Table of Contents


A while back I came across a Huawei E303 usb modem stick for next to nothing on eBay.

The modem itself is nothing great considering its data capabilities are pretty obsolete.

It does have one cool feature. It has a Web GUI for sending and receiving SMS messages. It also has an API which can be used on the command line.

This makes the modem handy to carry around as an emergency replacement for my mobile

I want to access it via the cloud

Main features:

  • Send text/sms messages from a web browser
  • Send text/sms remotely from the command line
  • Send alerts via txt
  • Query device info

The plan

The Web interface will be made available to the internet via SSH remote forwarding between my Raspberry Pi (this has the dongle connected) and a web server in the cloud. The internet facing web server will have HTTPS and password protection.

The neat thing is that the Raspberry Pi does not need to listen on any externally reachable ports, instead the RaspberryPi acts as an SSH client, initiating a connection to the cloud. The SSH "RemoteForward" option allows an SSH client to 'push' a port so that it is reachable on the remote SSH server.

Part 1: Configuration on the Pi

First plug the modem into your server and beware that it may automatically assign itself as the primary internet connection. Depending on your OS it will immediately show up as either as "enx582c80139263" or eth1 If you're not so lucky, you may need to run the command below, this instructs the modem to act as an ethernet device rather than an old fashioned modem

sudo usb_modeswitch -v 12d1 -p 1f01 "55534243123456780000000000000011062000000101000100000000000000"

Next, let's bring it online (if it hasn't automatically)

ip link set up enx582c80139263
ip addr add dev enx582c80139263
cat >> /etc/network/interfaces << EOF
    allow-hotplug enx582c80139263
    iface enx582c80139263 inet static

Part 2: Sending and receiving SMS

Now we'll learn how the API works and demonstrate sendding and receiving SMS messages. I have made a script containing most of the HiLink API functions.

chmod +x

$ ./ send_sms "Hello, World" 55512345678
<?xml version="1.0" encoding="UTF-8"?>

$./ get_sms
<?xml version="1.0" encoding="utf-8"?>
            <Content>Use 892223 to log in to Facebook.</Content>
            <Date>2018-03-19 23:43:58</Date>

Let's look at what's going on under the hood inside send_sms

    curl $curl_options \
    -X POST "$scheme://$host:$port/api/sms/send-sms" \
    -H "Cookie:$COOKIE" \
    -H "__RequestVerificationToken:$TOKEN" \
    -d "<request><Index>-1</Index><Phones><Phone>$2</Phone></Phones><Sca>$sca</Sca><Content>$3</Content><Length>${#3}</Length><Reserved>1</Reserved><Date>$(date '+%Y-%m-%d %T')</Date></request>"

Part 3: Tunnelling to the Frontend Server.

The command below initiates the ssh reverse tunnel which allows the cloud server to communicate with the dongle. This instance of SSH needs to be kept running. We can make this easier using AutoSSH, however this is beyond the scope.

On the Pi:

 ssh cloud_server -R 8088: -N &

Now log into the server and test it's working

$ curl http://localhost:8088/api/monitoring/check-notifications

<?xml version="1.0" encoding="UTF-8"?>

Part 4: Install and Configure Nginx

Generating the SSL certificate (with LetsEncrypt)

    sudo wget -O - | sh --issue --standalone -d

Create the username/password

htpasswd -c /etc/nginx/.htpasswd hilink
New password: 
Re-type new password: 
Adding password for user hilink

Configuring Nginx Virtualhost

Paste the following into /etc/nginx/sites-enabled/hilink
(Be sure to find-and-replace

server { 
    listen ssl;
    ssl_certificate /root/;
    ssl_certificate_key /root/;
    location ~ ^/$ {
        return 301;
    location / {
        auth_basic "Restricted";
        auth_basic_user_file /etc/nginx/.htpasswd;
        proxy_set_header Host;
        add_header Host;


We now should be able to access the Web UI. Try (replacing with our own domain)

If you wish to use my script, make sure you set the following environment variables

export $HILINK_PROTO=https 
export $
export $HILINK_AUTH="-u hilink:not_mY_r3a1_P@s5w0rd!!"

If you're noticing oddities, be careful about how you're entering the URL, because if the Hauweis web server isn't happy, it will reply with a redirect and your browser will try to reach

Part 5: API

In addition to the web interface, we can also use its XML-RPC based API so that we can automatically send an receive sms messages through scripts. (We covered this earlier) Perhaps to inform you of critical changes to a system.

We can also use the API to activate its modem, so it could be used with scripts to both fall over to 3G internet and text you if you loose connectivity. I'm still quite new to Web API stuff, so this section will be brief.

In these examples, we use the variable api_url which when interfacing with the dongle should be set to

5.1 - Activating/Deactivating the modem

#! /bin/bash

    curl $api_url/dialup/dial --data \

    #sudo ip route add to default via dev eth1 metric 1

    curl $api_url/api/dialup/dial --data \

    #sudo ip route del default via dev eth1 metric 1

5.2 - Network Information


<?xml version="1.0" encoding="UTF-8"?>

5.3 - Device information (IMEI etc)


<?xml version="1.0" encoding="UTF-8"?>

5.4 - Traffic Statistics

$ curl

<?xml version="1.0" encoding="UTF-8"?>

5.5 - Checking notifications

$ curl

<?xml version="1.0" encoding="UTF-8"?>

5.6 - USSD data

This script performs a USSD request using the code supplied in the first argument (for *123# supply 123 as the arg). It sends the request, waits 5 seconds, and then shows the response.

#! /bin/bash



    curl $api_url/ussd/send --data $request

    curl $api_url/ussd/get --data $request

sleep 5

For more API info check out

originally published on 2017-02-25