Currently, the market of VoIP software is dominated by software owned by big companies and tied to central infrastructure and the Internet in order to monetize the platform and control the data flow. On the other side there a various communities (e.g. Freifunk, Yggdrasil, ..) try to establish various kinds of decentralized networks to connect people with alternative pathways even without Internet. Common VoIP software usually does not work there. This is where Meshenger can serve as a use case or even "killer" App for these networks.
Meshenger has no discovery mechanism by design. Contacts are shared via QR-Code or text blob in JSON.
Connections are established via the addresses that are part of a contact. By default this is the link local address of the WiFi adapter. But the addresses in the contact can also contain other IPv4/IPv6 addresses or even domain names. This can be configured manually in the settings.
There are options to guess IPv6 addresses based on MAC addresses. But does not work if the MAC addresses of the WLAN device change, see MAC Randomization Behavior.
If the contacts address list contains an address that has a MAC address in it (like fe80:1122:33ff:fe44:5566/64 contains the MAC address 11:22:33:44:55:66), then extract the MAC address and add it to all of the IPv6 prefixes of the WLAN device. This new addresses are then also used to reach your contact. This works in scenarios when both participants both move from one network to another and the MAC address stays the same. This is rare due to todays Android security mechanisms, but might work for Freifunk networks that use the same SSID but different IPv6 prefixes.
Similar to "Guess IP Address", this mechanism looks for MAC addresses in a contacts address list and then tries to map the MAC to IPv4/IPv6 addresses that are stored in the local neighbor tables. These table are part of the systems IP mechanism to map IP addresses to a MAC address. But to parse this table is kind of implementation dependent, so it can break easily and is not recommended.
A call first starts on the caller side by creating a WebRTC offer. This a string that contains what video/audio codecs the phone supports and what IP addresses it has (ICE candidates). The offer is send via an initial TCP/IP connection to the callee by trying several of the contacts IP addresses one ofter another.
This initial connection is encrypted with the public key of the callee and signed by the private key of the caller.
When the packet with the offer is received on the callee side, it is passed to WebRTC which then establishes a UDP connection to the caller using the IP address and encryption key in the WebRTC offer. The initial connection will then be closed and the call connection is established.
Ideally, the offer being send should contain no IP addresses on send for privacy reasons and the caller address should be added on the receiving end before passing it to WebRTC. This is still a TODO (see filterOfferBeforeSend/completeOfferAfterReception methods in the source code).
Meshenger WebRTC, a well known library for video- and audio communication. It handles audio and video WebRTC also supports NAT traversal via ICE-Servers, but this feature has been turned off for Meshenger, because it is not needed. The special build of WebRTC adds a few patches from the Threema messenger and one own patch. See here.
- Serverless WebRTC Android demo
- Real time communication with WebRTC on Android documentation
- Getting Started with WebRTC for Android blog post
- WebRTC for Android blog post
- Android WebRTC tutorial
libsodium is used for the encryption and authentication of the initial TCP/IP connection (called signalling). After that, WebRTC is establishing a UDP connection for Audio/Video data. WebRTC uses it's own encryption.
The database contains the settings and contacts. It is stored in the internal/private file store of the app. If no password is used, the database is stored in plain text.
If a password is used, it will be salted and hashed using libsodium::crypto_pwhash. The hash is used as key for libsodium::crypto_secretbox_open_easy along with a nonce. The salt and nonce are stored along with the database and changed every time the database is stored.
The database file is prefixed with a four byte version header. Currently, it is set to zero.
Contacts identities are based on public/secret keys (ed25519). These are used to sign the WebRTC SDP offers using libsodium::crypto_sign and are then encrypted using libsodium.crypto_box_seal (X25519, XSalsa20-Poly1305) with the recipients public key (curve25519) derived from the identity key.
Every packet is prefixed with a four byte header. Currently it only contains the packet length.
The WebRTC connection itself uses its own crypto scheme.
Meshenger is Free and Open Source Software. Everybody can participate or even fork the software.
On Linux based systems:
./gradlew assembleRelease
Android Studio works as well.
Sometimes it is neccessary to look at the debug output to find out why something does not work. For this you need to install a debug build of Meshenger, enable the developer mode on Android and connect the phone via cable to your cmputer (there are other ways, but this might be the simplest one). Then execute this on the terminal of your computer:
sudo adb kill-server
sudo adb start-server
sudo adb logcat | grep `adb shell ps | grep d.d.meshenger | awk '{print($2)}'`
This project was sponsored by the Google Summer of Code 2018 as part of the Freifunk organization to make local community networks more attractive.
The development can be followed via the Freifunk blog:
This phase was concluded with Meshenger 1.0.0.
The second phase was to implement authentication/encryption of the WebRTC handshake and database encryption. Along with other usability features (e.g. backup), other contact addresses should be able to be used (e.g. hostnames, multicast groups).
This phase was concluded with Meshenger 2.0.0.
The third phase added better encryption, a call history and (re-) added unknown callers.
This phase was concluded with Meshenger 3.0.0.
This phase focuses on bug fixing, stabilization, usability improvements and some features.
This phase is concluded with the Meshenger 4.0.0 and further releases. Now an app with the intented features exists, which we hope serves as a use case for mesh networks without Internet and will help those in need.