Disclaimer: Low bandwidth Matrix is experimental, not yet standardised, and subject to change without notice.
This guide is for Matrix developers who want to support MSC3079: Low Bandwidth CS API in their clients/servers. Please read the experimental MSC if you want to learn more about what is happening at a protocol level. If you want a high level overview of low bandwidth Matrix and why you should care, watch the 12 minute demo on Matrix Live.
Matrix currently uses HTTP APIs with JSON data to communicate from the client to the server. This is widely supported but is not very bandwidth efficient. This means that the protocol is slower, more costly and less able to be used on low bandwidth links (e.g 2G networks) which are common in certain parts of the world. MSC3079 defines a low bandwidth protocol using CoAP and CBOR instead of HTTP and JSON respectively. In the future homeservers will natively support some form of low bandwidth protocol. However, at present, no homeserver natively supports MSC3079. Therefore, this guide will set up a low bandwidth proxy server which can be put in front of any Matrix homeserver (Synapse, Dendrite, Conduit, etc) to make it MSC3079-compatible. This guide will also configure an Android device to speak MSC3079.
Low bandwidth Matrix currently does not support web browsers due to their inability to send UDP traffic. You do not need to be running a homeserver to follow this tutorial.
Prerequisites:
openssl
to generate a self-signed DTLS certificate, or an existing certificate you want to use.Steps:
git clone https://github.com/matrix-org/lb.git
go build ./cmd/proxy
openssl ecparam -name prime256v1 -genkey -noout -out private-key.pem
openssl req -new -x509 -key private-key.pem -out cert.pem -days 365
# you now have cert.pem and private-key.pem
./proxy -local 'https://matrix-client.matrix.org' \
--tls-cert cert.pem --tls-key private-key.pem \
--advertise "http://127.0.0.1:8008" \
--dtls-bind-addr :8008
INFO[0000] Listening on :8008/tcp to reverse proxy from http://127.0.0.1:8008 to https://matrix-client.matrix.org - HTTPS enabled: false
INFO[0000] Listening for DTLS on :8008 - ACK piggyback period: 5s
Mac users: If you are having trouble generating EC certificates, make sure you are using OpenSSL and
not LibreSSL which comes by default: openssl version
. To use OpenSSL, brew install openssl
which
then dumps the binary to /usr/local/opt/openssl/bin/openssl
.
To test it is working correctly:
# build command line tools we can use to act as a low bandwidth client
go build ./cmd/jc
go build ./cmd/coap
# do a CoAP GET request to matrix.org via the proxy
./coap -X GET -k 'http://localhost:8008/_matrix/client/versions' | ./jc -c2j '-'
{"unstable_features":{"io.element.e2ee_forced.private":false,"io.element.e2ee_forced.public":false,"io.element.e2ee_forced.trusted_private":false,"org.matrix.e2e_cross_signing":true,"org.matrix.label_based_filtering":true,"org.matrix.msc2432":true,"org.matrix.msc3026.busy_presence":false,"uk.half-shot.msc2666":true},"versions":["r0.0.1","r0.1.0","r0.2.0","r0.3.0","r0.4.0","r0.5.0","r0.6.0"]}
If this doesn't work:
-v
to ./coap
(e.g bad method or path)SSLKEYLOGFILE=ssl.log
and inspect the decrypted traffic using Wireshark.Otherwise, congratulations! You now have a low bandwidth proxy! You can connect to your proxy just like you would to matrix.org or any other homeserver.
We'll add low bandwidth matrix to Element Android and iOS by default once it's standardised - but while things are still experimental, here's a guide for how to build Element Android to do it yourself if you feel the urge. This can be used as inspiration for other Matrix clients too.
Prerequisites:
Steps:
git clone https://github.com/vector-im/element-android.git
kegan/lb
: git checkout kegan/lb
. This branch replaces all HTTP traffic going to
/_matrix/client/*
with LB traffic. /_matrix/media
traffic is left untouched. This branch also
disables TLS checks entirely so self-signed certificates will work.git clone https://github.com/matrix-org/lb.git
go get golang.org/x/mobile/cmd/gomobile
cd mobile
# if gomobile isn't on your path, then ~/go/bin/gomobile
gomobile bind -target=android
mkdir $PATH_TO_ELEMENT_ANDROID_REPO/matrix-sdk-android/libs
cp mobile-sources.jar $PATH_TO_ELEMENT_ANDROID_REPO/matrix-sdk-android/libs
cp mobile.aar $PATH_TO_ELEMENT_ANDROID_REPO/matrix-sdk-android/libs
--advertise
address. If you are running on a local device, restart the
proxy with an --advertise
of your machines LAN IP e.g 192.168.1.2 instead of 127.0.0.1.
If you are running on an emulator, restart the proxy with an --advertise
of the
host IP:
10.0.2.2. The URL scheme should be https
not http
, else image loading won't work as Element
Android won't download media over http
.--advertise
address as the HS URL
e.g https://192.168.1.2:8008
or https://10.0.2.2:8008
. The port is important.To verify it is running via low bandwidth:
SSLKEYLOGFILE=ssl.log
.sudo tcpdump -i en0 -s 0 -v port 8008 -w lb.pcap
lb.pcap
in Wireshark and set ssl.log
as the Pre-Master Secret log filename via
Preferences -> Protocols -> TLS -> Pre-Master Secret log filename.To send a single 'Hello World' message to /room/$room_id/send/m.room.message/$txn_id
and receive the response, including connection setup:
Protocol | Num packets | Total bytes |
---|---|---|
HTTP2+JSON | 43 | 6533 |
CoAP+CBOR | 6 | 1440 |
/sync
sends back much more data than is strictly necessary. This
means the initial sync can be slower than expected. On a low kbps link this can flood the
network with so much data that the sync stream begins to fall behind. Future work will look
to optimise the sync API./versions
.