aboutsummaryrefslogblamecommitdiffstats
path: root/mds/howtogetyourSMSonIRC.txt
blob: 438e7b04286a5eff5d5bbc7a65e55e16e73888fb (plain) (tree)



































































































































































































































                                                                                                                                                                                                                                                                   
== How to get your SMS on IRC

It’s not really a continuation of the ``one client for everything'' post
but it is in the same vein. Basically, in this post we are going to make
it so that we receive our SMS messages on IRC. More specifically, it
will send it to a IRC channel. In my case this works and is actually
secure, since the channel I have the SMS going to is on my own IRC
network which only allows users in after they do a successful SASL
authentication.

The general idea is this:

* We run an app on our phone that will send the SMS to a web hook server
* The web hook server has an IRC client that will send the message to
the IRC channel

=== security considerations

==== SMS vs https://en.wikipedia.org/wiki/Rich_Communication_Services[RCS]

For forwarding the SMS I get on my cellphone from my cellphone to the
web hook server, i use
https://github.com/bogkonstantin/android_income_sms_gateway_webhook[android_income_sms_gateway_webhook].
This app does not support RCS(see
https://github.com/bogkonstantin/android_income_sms_gateway_webhook/issues/46[#46]).
For this to work, make sure your phone has RCS disabled unless you use
another app that supports RCS.

==== web hook server connection

The app will be connecting to our web hook server. The ideal way I
wanted to do this would be to connect to a VPN, only through which we
can access the web hook server. But its android not linux. I dont know
how I can do that on android so that’s a no go. Next idea is to use
local port mapping using openssh to send the SMS through the ssh tunnel.
While that is very feasible without rooting the phone, a one-liner in
termux can take care of it but automating it is a bit of a hassle.
Currently the only measure I am taking is to just use https instead of
http. Since we are using only tls we can use the normal TLS hardening
measures, server-side. We are using nginx as the reverse proxy. We will
also terminate the tls connection on nginx. We will be using
https://github.com/pocketbase/pocketbase[pocketbase] for the record
storage and authentication. We can extend pocketbase which is exactly
how we will be making our sms web hook. Pocketbase will give us the
record storage and authentication/registration we need. We will use
https://github.com/lrstanley/girc[girc] for our IRC library. My personal
IRC network wll require successful SASL authentication before letting
anyone into the network so supporting SASL auth(PLAIN) is a requirement.

We can use basic http authentication using our chosen app. We can
configure the JSON body of the POST request our web hook server will
receive. The default POST request the app will send looks like this: For
the body:

[source,json]
----
{
  "from": "%from%",
  "text": "%text%",
  "sentStamp": "%sentStamp%",
  "receivedStamp": "%receivedStamp%",
  "sim": "%sim%"
}
----

And for the header:

[source,json]
----
{ "User-Agent": "SMS Forwarder App" }
----

We get static cerdentials so we can only do basic http auth. We dont
need to encode the client information into the security token so we’ll
just rely on a bearer-token in the header for both authentication and
authorization.

==== Authentication and Authorization

In our case, the only resource we have is to be able to post anything on
the endpoint so in our case, authentication and authorization will be
synonimous. We can put the basic auth cerdentials in the url:

....
https://user:pass@sms.mywebhook.com
....

Also do please remember that on the app side we need to add the
authorization header like so:

[source,json]
----
{"Content-Type": "application/json"; "Authorization": "Basic base64-encoded-username:password"}
----

As for the url, use your endpoint without using the username and passwor
in the URI.

=== Dev works

You can find the finished code
https://github.com/terminaldweller/sms-webhook[here].

Here’s a brief explanation of what the code does: We launch the irc bot
in a goroutine. The web hook server will only respond to POST requests
on `/sms` after a successful basic http authentication. In our case
there is no reason not to use a randomized username as well. So
effectively we will have two secrets this way. You can create a new user
in the pocketbase admin panel. Pocketbase comes with a default
collection for users so just create a new entry in there.

* The code will respond with a 401 for all failed authentication
attempts.
* We dont fill out missing credentials for non-existant users to make
timing attacks harder. Thats something we can do later.

=== Deployment

[source,nginx]
----
events {
  worker_connections 1024;
}
http {
  include /etc/nginx/mime.types;
  server_tokens off;
  limit_req_zone $binary_remote_addr zone=one:10m rate=30r/m;
  server {
    listen 443 ssl;
    keepalive_timeout 60;
    charset utf-8;
    ssl_certificate /etc/letsencrypt/live/sms.terminaldweller.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sms.terminaldweller.com/privkey.pem;
    ssl_ciphers HIGH:!aNULL:!MD5:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_session_cache shared:SSL:50m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;
    ssl_prefer_server_ciphers on;
    tcp_nopush on;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options SAMEORIGIN always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "no-referrer";
    fastcgi_hide_header X-Powered-By;

    error_page 401 403 404 /404.html;
    location / {
      proxy_pass http://sms-webhook:8090;
    }
  }
}
----

[source,yaml]
----
version: "3.9"
services:
  sms-webhook:
    image: sms-webhook
    build:
      context: .
    deploy:
      resources:
        limits:
          memory: 256M
    logging:
      driver: "json-file"
      options:
        max-size: "100m"
    networks:
      - smsnet
    restart: unless-stopped
    depends_on:
      - redis
    volumes:
      - pb-vault:/sms-webhook/pb_data
      - ./config.toml:/opt/smswebhook/config.toml
    cap_drop:
      - ALL
    dns:
      - 9.9.9.9
    environment:
      - SERVER_DEPLOYMENT_TYPE=deployment
    entrypoint: ["/sms-webhook/sms-webhook"]
    command: ["serve", "--http=0.0.0.0:8090"]
  nginx:
    deploy:
      resources:
        limits:
          memory: 128M
    logging:
      driver: "json-file"
      options:
        max-size: "100m"
    image: nginx:stable
    ports:
      - "8090:443"
    networks:
      - smsnet
    restart: unless-stopped
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - DAC_OVERRIDE
      - SETGID
      - SETUID
      - NET_BIND_SERVICE
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - /etc/letsencrypt/live/sms.terminaldweller.com/fullchain.pem:/etc/letsencrypt/live/sms.terminaldweller.com/fullchain.pem:ro
      - /etc/letsencrypt/live/sms.terminaldweller.com/privkey.pem:/etc/letsencrypt/live/sms.terminaldweller.com/privkey.pem:ro
networks:
  smsnet:
    driver: bridge
volumes:
  pb-vault:
----

timestamp:1706042815

version:1.1.0

https://blog.terminaldweller.com/rss/feed

https://raw.githubusercontent.com/terminaldweller/blog/main/mds/howtogetyourSMSonIRC.md