Nowadays, SMS are widely used across web services. They are not aiming to replace bulk mail and they are generally used to identify a user more securely.
This list is just a few cases that come to my mind where you might want to send a text message to your users :
- Password recovery
- Two factor authentication
- Confirmation of an action with increased security
- Alert: it is known that a SMS will have a higher rate of lecture than an email
They are plenty of SMS provider online that can be used for sending SMS. They usually expose an HTTP API so you can send SMS over HTTP.
These provider are generally not free, despite the low pricing, for some developer this will still be to high for there need and it will be considered as not mandatory. This generally result in a weaker security strategy for your web service.
Hopefully, it's possible to build your home made SMS server with a minimal cost of 5 usd (not including the electricity).
For this, you will need the following:
- A Linux compatible USB 3G Modem
- A valid SIM card that support SMS sending
I bought the cheapest USB stick I could find on the internet from China, and prayed that it was supported by Linux, and it was.
It cost 7$. As a new Aliexpress customer, I also had a 2$ voucher, overall I had to pay 5$ and waited one month to receive it.
Regarding the SIM card, you must choose the right plan depending on the country where you will host your SMS server, but also the location of your users.
In my case, the server will be hosted in Paris (France), and since my ISP is offering to their customers a SIM card with free and unlimited SMS to french numbers, I started with this one.
If you are going to use an unlimited SMS plan, you should read carefully the general condition of it, sometimes broadband provider add limit such as the number of total recipients per month.
If you have both the SIM card and a modem, you should now set the pin to something easy, or disable the PIN code so it will be less configuration.
Prerequisites
Either you are using Docker or standalone installation, your GSM modem must be visible in the system. When you put a USB stick to your system, you have to see a new USB device:
dmesg | grep ttyUSB
or typing command:
lsusb
Bus 001 Device 009: ID 12d1:1406 Huawei Technologies Co., Ltd. E1750
My hardware support both SD card reader and mode, I have to use usb_modswitch to switch it to modem mode:
usb_modeswitch -W -v 05c6 -p 1000 -K
I'll also make this config persistent by adding this line to /etc/rc.local right before exit 0 (Debian).
Now lsusb return
Bus 001 Device 004: ID 05c6:6000 Qualcomm, Inc. Siemens SG75
Prevent rules to assign a wrong tty device
This is specific to my modem. I experienced my modem jumping from a tty port to another, since I mount the device using docker, this was ruining my server, hopefully you can assign dev rule to prevent this :
echo 'SUBSYSTEM=="tty", ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="6000", SYMLINK+="mobile"' | tee -a /etc/udev/rules.d/10-local.rules
sudo udevadm trigger
ls -l /dev/mobile
I picked up the vendor id and product id using the lsusb command
This will ensure your device is always mounted under /dev/mobile
Expose an HTTP server using Docker
We use Gammu to communicate with our sim card, it is a "phone" software written in C designed to work on both Windows and UNIX system. A quick GitHub search to get a ready to use soft : https://github.com/pajikos/sms-gammu-gateway
You can use the following docker compose file to start the service
version: '3'
services:
sms-gammu-gateway:
container_name: sms-gammu-gateway
restart: always
image: pajikos/sms-gammu-gateway
ports:
- "5000:5000"
devices:
- /dev/mobile:/dev/mobile
Run:
docker-compose up -d
When you run this application, you can simply send SMS using REST API:
POST http://xxx.xxx.xxx.xxx:5000/sms
Content-Type: application/json
Authorization: Basic admin password
{
"text": "Hello, how are you?",
"number": "+420xxxxxxxxx"
}
example:
AUTH=$(echo -ne "admin:password" | base64 --wrap 0)
curl -H 'Content-Type: application/json' -H "Authorization: Basic $AUTH" -X POST --data '{"text":"Hello, how are you?", "number":"+420xxxxxxxxx"}' http://localhost:5000/sms
1
If you need to customize the smsc number:
curl -H 'Content-Type: application/json' -H "Authorization: Basic $AUTH" -X POST --data '{"text":"Hello, how are you?", "number":"+420xxxxxxxxx","smsc": "+33695000695"}' http://localhost:5000/sms
or you can simply get the current signal strength:
GET http://xxx.xxx.xxx.xxx:5000/signal
and the response:
{
"SignalStrength": -83,
"SignalPercent": 45,
"BitErrorRate": -1
}
That's it, you have a quick and clean running free sms server running.
To think further, you could have many instances of this basic and secure endpoint for multiple SIM card and use a more complexe back end with fancy features such as:
- deciding which sim card to use when sending an sms
- reading response and replying to original user
- handle roundrobin
- away message
- handle available credit with broadband provider
- credit system for users
- ...