1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
|
== 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
|