SRV records for XMPP over TLS

From MattWiki
noteThis Page was written with Ubuntu 18.04 LTS in mind, and may not work correctly with other versions or distributions.


XMPP Portal
XMPP Servers: Servers Category
XMPP Clients: Clients Category
User Guides: User Guide Category

This artical will walk you through implementing XEP-0368: SRV records for XMPP over TLS on a Prosody version 0.10 XMPP server, running on Ubuntu version 16.04 LTS server. This will allow users to connect to the XMPP server while connecting through a restrictive firewall that blocks port 5222. This also adds that ability for a client to connect directly a TLS port instead of a STARTTLS port, this allows for a slightly quicker connection (in theory).[1]

Overview

The concept of the XEP-0368 standard is to allow users to connect to the xmpp server via port 443, but still allow HTTPS traffic to flow over the same port. This is accomplished by installing the program sslh that will sit in front of both the web server and the xmpp server and splits the connection between them.

  • When a client connects via port 5222, they connect via STARTTLS directly to XMPP Server port.
  • When a client connects via port 5223, they connect via direct TLS directly to XMPP Server port.
  • When a client connects via port 443, they connect via TLS to sslh that will then redirect the connection to XMPP Server port 5223.

Install SSLH from Source

You must install sslh with ALPN support; sslh version 1.18 or greater.[2]

To start out with, you must install the below prerequisites, on ubuntu[2], use the following command:

apt install git libwrap0-dev libconfig8-dev libpcre3-dev

After you have installed the prerequisites, download the git repository for sslh

mkdir -p /var/src && cd /var/src/
git clone --depth=1 https://github.com/yrutschle/sslh.git

And findlay, go into into the source sslh directory to compile and install the code.

cd /var/src/sslh/
make install

After the software is installed, copy the init file to start sslh.

cp scripts/etc.init.d.sslh /etc/init.d/sslh

Configuring SSLH for XMPP and HTTPS Traffic

You must create and/or update the /etc/sslh.cfg file.

The host entry, that is currently im.example.org, must be changed to you XMPP server's DNS Host Name.

verbose: 0;
foreground: false;
inetd: false;
numeric: false;
transparent: false;
timeout: 2;
user: "nobody";
pidfile: "/var/run/sslh.pid";
syslog_facility: "auth";

# Change hostname with your external address name. Note: It should not be resolving to 127.0.0.1
listen:
( 
    { host: "im.example.com"; port: "443"; } 
);

protocols:
(
     #{ name: "ssh"; service: "ssh"; host: "localhost"; port: "22"; keepalive: true; fork: true; },
     { name: "http"; host: "localhost"; port: "443"; log_level: 0;},

     # just match ALPN
     { name: "tls"; host: "localhost"; port: "5223"; alpn_protocols: [ "xmpp-client" ]; log_level: 1;},
     { name: "tls"; host: "localhost"; port: "443"; alpn_protocols: [ "h2", "http/1.1", "spdy/1", "spdy/2", "spdy/3" ]; log_level: 0; },

     # just match SNI
     { name: "tls"; host: "localhost"; port: "5223"; probe: "builtin"; sni_hostnames: [ "example.com" ]; log_level: 1;},
     { name: "tls"; host: "localhost"; port: "5223"; probe: "builtin"; sni_hostnames: [ "example2.com" ]; log_level: 1;},
     { name: "tls"; host: "localhost"; port: "5223"; probe: "builtin"; sni_hostnames: [ "example3.com" ]; log_level: 1;},
     { name: "tls"; host: "localhost"; port: "443"; probe: "builtin"; sni_hostnames: [ "im.example.com" ]; log_level: 0; },
     { name: "tls"; host: "localhost"; port: "443"; probe: "builtin"; sni_hostnames: [ "im.example2.com" ]; log_level: 0; },
     { name: "tls"; host: "localhost"; port: "443"; probe: "builtin"; sni_hostnames: [ "im.example3.com" ]; log_level: 0; },

     # catch anything else TLS
     { name: "tls"; host: "localhost"; port: "443"; log_level: 0;},

     # Jabber
     { name: "regex"; host: "localhost"; port: "5222"; regex_patterns: [ "jabber" ]; log_level: 1;},
     { name: "regex"; host: "localhost"; port: "443"; regex_patterns: [ "jabber" ]; log_level: 0;},

     # Catch-all
     { name: "regex"; host: "localhost"; port: "443"; regex_patterns: [ "" ]; log_level: 0;}
);

on-timeout: "timeout";

Once complete, you must also set RUN=yes in the /etc/default/sslh file.

Web Server Changes

Since SSLH needs to use port 443 on the server's network interface, you must set your web server to listen to the loopback interface for any host that is using port 443.

Using Nginx

When using nginx, you must change all entries that are listening on the https port (443) to use the localhost interface and not the same interface SSLH is attached to.

In the below example, the IPv4 host is changed to localhost, and the IPv6 host is changed to ::1 .

    server {
        listen localhost:443 ssl http2;
        listen [::1]:443 ssl http2;
        server_name im.example.com;
        server_name conference.example.com;
        server_name upload.example.com;

This must be done for EVERY entry within nginx.

Changes to be made on the XMPP Server

ejabberd Changes

By default, ejabberd should already be configured to allow XEP-0368 connects. You may confirm that required sections are enabled.

Default XMPP client port

listen:
  -
    port: 5222
    ip: "::"
    module: ejabberd_c2s
    starttls_required: true
    shaper: c2s_shaper
    access: c2s

Direct-TLS XMPP client port

  -
    port: 5223
    ip: "::"
    module: ejabberd_c2s
    tls: true
    shaper: c2s_shaper
    access: c2s

Prosody Changes

Prosody needs to allow connections from clients via TLS (not STARTTLS). This is done by enabling legacy SSL support by adding the below line in the global section of your prosody.cfg.lua:

legacy_ssl_ports = 5223;

DNS Changes

And finally, we need to make the required DNS Changes.

The XEP-0368[3] states that

In this example, the XMPP host (im.example.org) is listening for clients on ports 5223, 5222, and 443.

# Clients will try in the following order, 5223/tls, 5222/xmpp, 443/tls
_xmpps-client._tcp.example.org. 86400 IN SRV 5  1 5223 im.example.org.
_xmpp-client._tcp.example.org.  86400 IN SRV 10 1 5222 im.example.org.
_xmpps-client._tcp.example.org. 86400 IN SRV 15 1 443 im.example.org.
_xmpp-client._tcp.example.org.  86400 IN SRV 20 1 443 im.example.org.

The client will first try to connect to port 5223, if it is unable to, it will then try port 5222, if it is unable to, it will then try port 443.

Testing

References

  1. "XEP-0368: SRV records for XMPP over TLS § Introduction". 2017-03-09. Retrieved 2017-08-05. 
  2. 2.0 2.1 "Installing Prosody § XMPP over HTTPS". Retrieved 2017-08-05. 
  3. "XEP-0368: SRV records for XMPP over TLS § Requirements". 2017-03-09. Retrieved 2017-08-05. 

Notes