Magazine

Envío de mensajes SMS con modems Huawei HiLink

Publicado el 23 noviembre 2023 por Alejsanc @cdrninformatica

Envío de mensajes SMS con modems Huawei HiLink

Los módem Huawei HiLink tienen dos modos de funcionamiento: módem normal o router WiFi. Por defecto funcionan como un router WiFi, al conectarse al puerto USB del ordenador le proporcionan un dispositivo de red y tienen un punto de acceso WiFi al que pueden conectarse otros dispositivos. En modo router no es posible utilizar comandos AT para controlar el dispositivo, es necesario utilizar su servicio web. En este artículo voy a explicar como utilizar el servicio web para enviar mensajes SMS.

Envío de mensajes SMS con modems Huawei HiLink

Por defecto la dirección IP del router es 192.168.8.1 y el usuario para conectar "admin". En el dispositivo se indica la contraseña. Para comunicarnos con el servicio web podemos utilizar cualquier lenguaje de programación. Yo he usado el interprete de comandos Bash y algunos programas como el cliente HTTP cURL.

#!/usr/bin/bash

SERVER=192.168.8.1
USERNAME="admin"
PASSWORD="xxxxxxxx"

En primer lugar debemos solicitar un ID de session y un "token" en la dirección /api/webserver/SesTokInfo. Recibiremos un documento XML, con el comando xmllint podemos extraer los datos que necesitamos utilizando XPath.

info=`curl -s http://$SERVER/api/webserver/SesTokInfo`

session=`echo $info | xmllint --xpath "/response/SesInfo/text()" -` 
token=`echo $info | xmllint --xpath "/response/TokInfo/text()" -`
<response><SesInfo>6MOMvUWALNM6aPQEZOTIHYuVEBC1C91u7Vd4f8MBdKx0BsxUjQ0Rceal8cyc8n4Qm7hUoIUOcOH40KLPEy743mUlySXQYAendJT00iu53uqLtUHrc2XL8bBW0vZVHhpC</SesInfo><TokInfo>TEQxGdHf0jU3w0B0o2WtL3meQrcPRJxq</TokInfo></response>

El siguiente paso es realizar la autenticación en el servicio web para tener permiso de ejecución de acciones. Para ello es necesario enviar un documento XML a la dirección /api/user/login con el usuario, la contraseña y el tipo de contraseña. Debemos usar el ID de sesión y el "token" obtenidos anteriormente.

login="<request><Username>$USERNAME</Username><Password>$hash</Password><password_type>4</password_type></request>"

login_response=`curl -i -s -b "SessionID=$session" -H "__RequestVerificationToken: $token" -d "$login" http://$SERVER/api/user/login`

Dependiendo del modelo de módem necesitaremos un tipo de contraseña diferente. Para el tipo 4 debemos en primer lugar hacer una "hash" SHA-256 de la contraseña y codificarla en Base64. A continuación hay que unir el usuario, el "hash" de la contraseña y el "token" en una cadena de texto. Por último debemos hacer el "hash" SHA-256 de esta cadena y codificarla en Base64. El resultado es lo que hay que usar en el parámetro Password del documento XML.

sha256base64 () {
	hash=`echo -n $1 | sha256sum | cut -d " " -f 1 | tr -d "\n" | base64 -w 0`
}

sha256base64 "$PASSWORD"
sha256base64 "$USERNAME$hash$token"

Al realizar la autenticación recibiremos una respuesta con la "cookie" SessionID con un nuevo ID de sesión y varias cabeceras con "tokens" para realizar acciones. Si solo queremos realizar una o dos acciones nos basta con leer las cabeceras __RequestVerificationTokenone y __RequestVerificationTokentwo. En la cabecera __RequestVerificationToken se encuentran esos dos "tokens" y algunos más separados por el carácter "#".

Set-Cookie: SessionID=KStfxWIiy8jlXbCrfP4zdkljk1BUvs84s8HQxckZz4obgTVtTpydBP87PO4cvjhAhqWSRsXkWCP7hLhBCQ70VR4Cydh7LXNYMYVnQfWKaXcPq7y4e7eBTWj00nR9Byla; path=/; HttpOnly;
__RequestVerificationTokenone: Bj02gvGS5bX80xfyhI32Jue69sAayt1Y
__RequestVerificationTokentwo: 0YO0Piy6RjWToDYuwC4uPl65ZZHF0yJv
__RequestVerificationToken: Bj02gvGS5bX80xfyhI32Jue69sAayt1Y#0YO0Piy6RjWToDYuwC4uPl65ZZHF0yJv#g23cIa8CG1QM6PLq5p0a0E0uzaYBALqW#R9rbWeZLmw0OGCd4oY5P2PHS0A2J9NIp#GOdHohrOjgB4mqkXN6X01Bm0cK1ulyyD#lQhntCogUbJ1kpEk45kqGJ5qNnqp9iuh#ADV1dYflDsm1mxpmBMwbeyN21jYTgYlv#TpfvkhBuZXjhmTepci5qVaZEQkeMuuKI#wyU6zQWvqNsyqtJ420s3mGNL0XV3Negx#a1s3OUp7yALiY9Yel473R0ymEPNLSD0D#imFzzR0lpQXdrHauh1u3GMCjSKBBDER6#GXbKBZ0BSXXpCZQucwIaPEt0R5GzvX7i#d8KqyjkmBiW81NHZXIsLMNW3q10EWXme#dDH3nhfJ09IAxFgqGkvckQSYGPf0kFYX#eNGn9TKmJ8EwFySmlcCKB1lyDGxSLvYn#cfcBw0XJyDqO31PxMdMDhZzCR1toaIPl#0ZFxajlHwK3eerw8h5tTYNORjJANd9RA#D1tGSDh3udWlROrUpKKYQAAdYMKytJiP#PNswsMQ3zW0e9bY2020OuoriSJEZf0oL#IVvt0050Eka5R4Ro0Ok4kawrMGI7BBy3#ww0qQSHq0a8VGgyXUQiyokp0gWtTc8zg#K0AXbLnRcpvWyx0Cgkn3XL8f0t7Heh0d#Y2AMqOdnaYXRXb5QwHyRZViNvcTMje7N#nmW4XjcjZsNGprw4mgMuNQ08rHLrf9zK#Mi9GmNorbl0iW0lL2YBqLCSIEoxA9T0k#xRAcG0ss42dX0c1DMc0MAqAroGN01oXl#rBfOzhcLOklRY0gMo1tHnpEocbkHuojF#LWDJoEpY7v5neIRWwzJV4hFjU69en5k4#FH9t6cc4En1XyvztexerCHsXyXmOEvaL#bxKPUfszcdLqpZK6S3K4ZIpPATZLGgKS#UXSF7hgjiAag0DjF0OgXd0umpOi4is2B#ksjbqLoj0ddIFDdDuVTPxPDIsIwQQgjb
session=`echo "$login_response" | grep -o "SessionID=[0-9a-zA-Z]*" | cut -d "=" -f 2`
token=`echo "$login_response" | grep -o "__RequestVerificationTokenone: [0-9a-zA-Z]*" | cut -d " " -f 2`

Con estos ID de sesión y "token" ya podemos mandar un mensaje SMS enviando un documento XML a la dirección /api/sms/send-sms. En este documento se indican los números de teléfono de los destinatarios, el mensaje, la longitud del mensaje y la fecha.

phone=$1
content=$2
length=${#content}
date=`date "+%F %H:%M:%S"`

sms="<request><Index>-1</Index><Phones><Phone>$phone</Phone></Phones><Content>$content</Content><Length>$length</Length><Reserved>1</Reserved><Date>$date</Date></request>"

sms_response=`curl -s -b "SessionID=$session" -H "__RequestVerificationToken: $token" -d "$sms" http://$SERVER/api/sms/send-sms`

Como respuesta obtenemos otro documento XML con el resultado del envío. Si se realizó correctamente recibiremos la cadena de texto "OK". De lo contrario recibiremos un número de error.

<response>OK</response>
<error><code>100005</code><message></message></error>
result=`echo $sms_response | xmllint --xpath "/response/text()" -`

if [[ $result == "OK" ]]
then
	exit 0
else
	exit 1
fi

El servicio web permite otras muchas acciones y hay varias bibliotecas en múltiples lenguajes de programación para utilizarlo. Podemos usar estas bibliotecas para interactuar con el servicio web o nos pueden servir como fuente de información para desarrollar nuestro propio código. A continuación se muestra el "script" completo para el envió de mensajes, se le deben pasar como parámetros el número de teléfono y el mensaje. También está disponible en un repositorio de GitHub.

./send-sms.sh XXXXXXXXX "Prueba de mensaje SMS"
#!/usr/bin/bash

SERVER=192.168.8.1
USERNAME="admin"
PASSWORD="xxxxxxxx"

sha256base64 () {
	hash=`echo -n $1 | sha256sum | cut -d " " -f 1 | tr -d "\n" | base64 -w 0`
}

phone=$1
content=$2
length=${#content}
date=`date "+%F %H:%M:%S"`

info=`curl -s http://$SERVER/api/webserver/SesTokInfo`

session=`echo $info | xmllint --xpath "/response/SesInfo/text()" -` 
token=`echo $info | xmllint --xpath "/response/TokInfo/text()" -`

sha256base64 "$PASSWORD"
sha256base64 "$USERNAME$hash$token"

login="<request><Username>$USERNAME</Username><Password>$hash</Password><password_type>4</password_type></request>"
login_response=`curl -i -s -b "SessionID=$session" -H "__RequestVerificationToken: $token" -d "$login" http://$SERVER/api/user/login`

session=`echo "$login_response" | grep -o "SessionID=[0-9a-zA-Z]*" | cut -d "=" -f 2`
token=`echo "$login_response" | grep -o "__RequestVerificationTokenone: [0-9a-zA-Z]*" | cut -d " " -f 2`

sms="<request><Index>-1</Index><Phones><Phone>$phone</Phone></Phones><Content>$content</Content><Length>$length</Length><Reserved>1</Reserved><Date>$date</Date></request>"
sms_response=`curl -s -b "SessionID=$session" -H "__RequestVerificationToken: $token" -d "$sms" http://$SERVER/api/sms/send-sms`

result=`echo $sms_response | xmllint --xpath "/response/text()" -`

if [[ $result == "OK" ]]
then
	exit 0
else
	exit 1
fi

Volver a la Portada de Logo Paperblog