Introduction
In this tutorial, I will show how you can make your own private XMPP server, where you will have full control of your user data, messages, groups, files, all of that federated over anonymizing networks such as tor and i2p.
Requirements
XMPP over i2p
I2pd tunnel configuration
To make your prosody server federate over i2p, you need to create the necessary tunnels.
- Find where are your tunnels.conf file(see here for more info) or create one in your i2pd directory and add these lines to the file:
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[prosody-s2s]
type=server
host=127.0.0.1
port=5269
inport=5269
inbound.quantity = 2
outbound.quantity = 2
keys=prosody.dat
[prosody-c2s]
type=server
host=127.0.0.1
port=5222
inport=5222
inbound.quantity = 2
outbound.quantity = 2
keys=prosody.dat
[prosody-s2s-muc]
type=server
host=127.0.0.1
port=5269
inport=5269
inbound.quantity = 2
outbound.quantity = 2
keys=prosodymuc.dat
[prosody-c2s-muc]
type=server
host=127.0.0.1
port=5222
inport=5222
inbound.quantity = 2
outbound.quantity = 2
keys=prosodymuc.dat
[prosody-http]
type=server
host=127.0.0.1
port=5280
inport=5280
keys=prosodyfile.dat
[prosody-https]
type=server
host=127.0.0.1
port=5281
inport=5281
keys=prosodyfile.dat
We’re creating 3 different b32 addresses, which the keys are stored in prosody.dat, prosodymuc.dat and prosodyfile.dat, I will explain each address.
1 | [prosody-s2s] |
This first address is the main address, each user in the server will have this address in their JID, for example: user@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.b32.i2p.
The port 5269 will be used for server-to-server connections, this is where your server will be able to talk to other servers federated in i2p network.
The port 5222 will be used for client-to-server connections, this is where your xmpp client(in this tutorial, monocles chat) will talk to your server.
The inbound/outbound quantity are the amount of tunnels that this b32 address will have for receiving/sending data over i2p network, since this b32 address will not have a huge flow of data, I decided to configure less tunnels to avoid wasting i2p network resources.
1 | [prosody-s2s-muc] |
This second address is used for groups, also called MUC(Multi-User Chat), each group in your server will have this format: group@yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy.b32.i2p.
The ports 5269 and 5222 do essentially the same as in the first address.
1 | [prosody-http] |
This third address will be used for prosody file sharing server, every time a user uploads a file it will be sent to this server, and other people in the chat will be able to download the file.
The port 5280 is used for http, and the port 5281 is used for https.
- Run i2pd using this configuration.
- See the addresses generated in i2pd webconsole(http://127.0.0.1:7070/?page=i2p_tunnels). You will use these addresses in prosody configuration.
Prosody configuration
Find the directories your prosody server will use, just type this in the terminal:
1
prosodyctl about
Go the path of “Data directory” and make a new folder inside called “custom_plugins”, then git clone the plugin needed to prosody work over i2p:
1
2
3mkdir custom_plugins
cd custom_plugins
git clone https://github.com/majestrate/mod_darknetGo to the path of “Config directory” shown in the first step and open the “prosody.cfg.lua” file.
You will find a line with this configuration:1
VirtualHost "localhost"
Change this line with:
1 | VirtualHost "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.b32.i2p" |
Replacing “xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.b32.i2p” with prosody-s2s/prosody-c2s b32 address you got in i2pd webconsole.
Replacing “yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy.b32.i2p” with prosody-s2s-muc/prosody-c2s-muc b32 address you got in i2pd webconsole.
Replacing “zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.b32.i2p” with prosody-http/prosody-https b32 address you got in i2pd webconsole.
- Generate certificates for each b32 address:
1
2
3prosodyctl cert generate xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.b32.i2p
prosodyctl cert generate yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy.b32.i2p
prosodyctl cert generate zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.b32.i2p
In each certificate generation it will ask some information, you can skip a field with “.” in the input.
Move the certificate files from the “Data directory” to the folder “certs” in “Config directory”:
1
2cd path/to/data/
mv *.b32.i2p.* path/to/config/certsCheck everything with:
1
prosodyctl check
If you got “All checks passed, congratulations!”, you are almost ready to go!
Adding your user
Create your user with:
1 | prosodyctl adduser your_username_here@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.b32.i2p |
It will ask for a password, remember to put a strong password!
Running prosody
You are ready! Just start the server:
1 | prosodyctl start |
XMPP over tor
Tor hidden service configuration
Making your prosody server federate over tor is similar to i2p(it is actually a bit easier!).
Create a folder for your hidden service, in this example I will use a folder called “xmpp_hidden_service”
Create your hidden service, go to your torrc file and add these lines:
1
2
3
4
5HiddenServiceDir /path/to/xmpp_hidden_service
HiddenServicePort 5222 127.0.0.1:5222
HiddenServicePort 5269 127.0.0.1:5269
HiddenServicePort 5280 127.0.0.1:5280
HiddenServicePort 5281 127.0.0.1:5281Run tor using this torrc file and check your hidden service folder, you will find a file called “hostname”, this is your onion address, and it will look like this:
1
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.onion
Each port used in the torrc config serves the same purposes as the ones in i2p config.
Prosody configuration
Install “mod_onions” plugin to be able to federate over tor.
1
prosodyctl install --server=https://modules.prosody.im/rocks/ mod_onions
Go to your prosody.cfg.lua file(remember you can find your config file typing “prosodyctl about”) and add these lines after the i2p configuration:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15VirtualHost "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.onion"
modules_enabled = { "onions" };
onions_only = true;
disco_items = {
{ "conference.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.onion", "Public Chatrooms" };
{ "upload.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.onion", "Upload Files" };
}
Component "conference.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.onion" "muc"
modules_enabled = { "onions" };
onions_only = true;
Component "upload.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.onion" "http_file_share"
modules_enabled = { "onions" };
onions_only = true;
Replacing “aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.onion” with the onion address you got on “hostname” file from your hidden service folder.
Generate the certificate for your onion address:
1
prosodyctl cert generate aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.onion
Move the certificate files from the “Data directory” to the folder “certs” in “Config directory”:
1
2cd path/to/data/
mv *.onion.* path/to/config/certsCheck everything with:
1
prosodyctl check
Adding your user
Create your user with:
1 | prosodyctl adduser your_username_here@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.onion |
Running prosody
You are ready! Just start the server:
1 | prosodyctl start |
Login to your user in monocles chat
I2p
Turn on your i2pd router in your phone, you can use their app for this.
Open monocles chat and go to the login page.
Click “I have an account”.
Go to the config button(“⋮”) and go to configurations, then select “Expert settings” and check “Connect via I2P”.
Go back to login, put in “hostname” your main b32 address, and in “ID Jabber” put your JID, like this:
1
2hostname: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.b32.i2p
ID Jabber: user@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.b32.i2pPut your password and click “Next”.
Accept the certificate of your server and you are ready to go!
Tor
Turn on tor, you can use orbot for this.
Open monocles and go to login page.
Click “I have an account”.
Go to the config button(“⋮”) and go to configurations, then select “Expert settings” and check “Connect via Tor”.
Go back to login, put in “hostname” your onion address, and in “ID Jabber” put your JID, like this:
1
2hostname: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.onion
ID Jabber: user@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.onionPut your password and click “Next”.
Accept the certificate of your server and you are ready to go!
Optional: other prosody configurations that you may want to change
Message archiving(mod_mam)
Uncomment mod_mam to make your server store messages.
1 | change this line: |
Change this config to set the expiration time of your messages:
1 | archive_expires_after = "1w" -- Remove archived messages after 1 week |
You can set the value to any time you want, including “never” to never delete your messages(this is YOUR private server, if you have good amount of storage, go ahead, you have FULL CONTROL over your data! ;D).
Check more about mod_mam here.
Server limits(mod_limits)
Change the bandwidth limits by your choice in these lines:
1 | limits = { |
Check more about mod_limits here.
Multi-User Chat archiving(mod_muc_mam)
Go to your MUC component and add mod_muc_mam to “modules_enabled”:
1 | tor: |
Like in mod_mam, you can set the expiration time of the messages in MUCs, for example:
1 | tor: |
Check more about mod_muc_mam here.
Files archiving(mod_http_file_share)
Go to your http_file_share component and add the config lines you want, for example:
1 | tor: |
Check all the configurations of mod_http_file_share here.
Group photo(mod_vcard_muc)
Install the required plugin:
1
prosodyctl install --server=https://modules.prosody.im/rocks/ mod_vcard_muc
Add “mod_vcard_muc” to “modules_enabled” in your MUC component:
1
2
3
4
5
6
7
8
9tor:
Component "conference.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.onion" "muc"
modules_enabled = { "onions", "vcard_muc" };
onions_only = true;
i2p:
Component "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy.b32.i2p" "muc"
modules_enabled = { "darknet", "vcard_muc" };
darknet_only = true;
Message moderation in groups(mod_muc_moderation)
Install the required plugin:
1
prosodyctl install --server=https://modules.prosody.im/rocks/ mod_muc_moderation
Add “mod_muc_moderation” to “modules_enabled” in your MUC component:
1
2
3
4
5
6
7
8
9tor:
Component "conference.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.onion" "muc"
modules_enabled = { "onions", "muc_moderation" };
onions_only = true;
i2p:
Component "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy.b32.i2p" "muc"
modules_enabled = { "darknet", "muc_moderation" };
darknet_only = true;
Optional: make your server public
Prosody is private by default to avoid abuse of spammers, meaning that with the current setup showed in this tutorial, the only user of your server will be you.
If you have a good hardware, you may want to run a public server for other people to join, or just want a server for your private community.
You have 2 ways to allow other people to register in your server.
- Create a register invite for each participant you want to join your server
First, add these 2 lines to your prosody.cfg.lua before the lines with “VirtualHost”:
1 | allow_registration = true |
Then, create a register invite in your terminal:
1 | tor: |
You will get something like:
xmpp:your_address?register;preauth=ramdom_token
Create a QR Code with this invite and send to the person you want to register. For this method, the person needs to have a xmpp client installed that recognizes this invite(like Monocles chat).
The invite will work for only one account, so you will need to generate a invite for every person you want to register in your server.
- Allow ANYONE to register in your server(be carefull with this option)
First, add these 2 lines to your prosody.cfg.lua before the lines with “VirtualHost”:
1 | allow_registration = true |
Anyone with a xmpp client will be able to register in your server, so you need to be carefull with spammers.
Check more about register here.
Check more about invites here.
Check best practices for public servers here.
Pros and Cons of making your own XMPP server over tor/i2p (In my opinion)
Pros:
- Full control of your data.
- Anyone can make a server, since tor/i2p domains are free.
- Very lightweight server.
- Location of your server and user will be hidden.
- Having the benefits of a p2p messenger(like briar), without the problems of p2p messenger(like group syncronization problems).
Cons:
- You will only be able to talk with other people that has a similar setup inside tor/i2p. (Good reason to share this tutorial to more people :D)
- Not all XMPP clients will work with this setup, but if this setup gets more popular, hopefully this will change. (For example, Dino does not handle onion/i2p addresses, gajim works with DMs and MUCs, but fails with file download)
- Slow connection, mostly with sharing files. (In monocles chat, for example, I frequently got “timeout error” when trying to send videos, but maybe this can be fixed setting a higher timeout when using tor and i2p in their source code)
- You need some kind of knowledge to setup this, and a hardware running 24/7.
Test your setup!
If you were able to create your server successfully, I created a group in my server in tor and i2p, so people can join and test their setup.
Tor:
test@conference.fs5l6swbq4poj4w5otvl5qqrmhpk5xklhlibe4tksmd63mlievka6vid.onion
I2p:
test@sdmmzcx2b7t4rhqqa5qczjao2sqgys3hdlmamzth4vjozeafblea.b32.i2p
Donation
If you liked my tutorial, please consider donating!
XMR:
1 | 46fhAp18FE9gNKcdeouJmGLpNZmfL2aUmMUcYfFqoRuhPfA1iXf5ojMcDHLc1Yco1qYNahc8WmkuEh2kmVCtymVABEQrJSL |
XNO:
1 | nano_1xepodzhxporqyy7ezaz1q8jfoc7q3x5n9tsus58ro5swczf3pegco44h75m |
BTC:
1 | bc1qtqx7kqt5t04uzhayhrnlx8f8hjw959vp9hclmg |