Nginx and XMPP over TLS
XMPP over TLS (formerly XEP-0368) is a clever mechanism that allows users to
connect to a XMPP server from networks that restrict outgoing traffic only to
specific ports; this block is circumvent by routing XMPP traffic via port TCP
443.
If the server hosts only a XMPP server setting up XMPP over TLS is pretty easy,
just instruct the server to listen on port 443.
If the server also runs a webserver which is listening on port 443 things are a
bit more complicated; luckily Nginx provides a way to manage XMPP traffic and
redirect it to the XMPP server.
$ cat /etc/nginx/nginx.conf
stream {
upstream httpserver {
server localhost:8443; # webserver_host:webserver_port
}
upstream xmppserver {
server localhost:5223; # xmpp_server_host:xmpp_over_tls_port
}
map $ssl_preread_alpn_protocols $upstream {
default httpserver;
"xmpp-client" xmppserver;
}
server {
listen 443;
ssl_preread on;
proxy_pass $upstream;
}
}
Also be sure to change Nginx virtual hosts accordingly, those should listen to port TCP 8443 instead of the usual TCP 443.
$ cat /usr/local/etc/ejabberd/ejabberd.yml
listen:
-
port: 5223
ip: "::"
module: ejabberd_c2s
max_stanza_size: 65536
shaper: c2s_shaper
access: c2s
tls: true
scheme: _service._proto.name TTL class SRV priority weight port target
_xmpps-client._tcp.example.org. 86400 IN SRV 5 0 443 xmpp.example.org.
_xmpp-client._tcp.example.org. 86400 IN SRV 10 0 443 xmpp.example.org.
_xmpp-client._tcp.example.org. 86400 IN SRV 15 0 5222 xmpp.example.org.
$ semanage port -l | grep http_port_t
http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000
Ejabberd should have no issues to bind port TCP 5223, the only thing left to do
is create a SELinux module to allow Nginx from redirecting traffic from port
TCP 443 to TCP 5223.
Be sure to have auditd service installed and running and also the
package policycoreutils-python installed on your system.
To create a new SELinux module run:
$ ausearch -c 'nginx' --raw | audit2allow -M nginx-xmppovertls
$ semodule -i nginx-xmppovertls.pp