Trunking Guide
Introduction
Openfire can be configured to act as a gateway to transfer data between other XMPP domains. This document covers what the use-cases for such a setup, how to configure this functionality, and what known caveats with this approach are.
The following sections are available in this document:
Use cases
The trunking functionality of Openfire is typically used in one of two scenarios:
- Connection Mediation (allow data to flow between remote XMPP domains)
- Data Monitoring / Filtering (ensure that only allowable data enters or leaves an XMPP domain
Use Case: Connection Mediation
The architecture of an XMPP network is similar to email; anyone can run their own XMPP domain and there is no central master domain. This federated open system approach allows users to interoperate with others on any domain. When users of one domain address data to users of another domain, servers of each domain will establish point-to-point connections between each-other, over which the data is exchanged. Multiple domains connecting to each other in a point-to-point manner creates a mesh-style network, as illustrated in figure 1.
In certain environments, it is undesirable to have a mesh-style network. When, for example, it is hard or undesirable to create and maintain many technical connections, or when central auditing of data is desirable (see Use Case: Data Monitoring / Filtering), then a Hub-and-Spoke network model, as shown in figure 2 is often a better fit than a mesh-style network. The main advantage of this style is that all domains only need to create and maintain a single connection to a single entity: the central hub. This central hub manages and passes through connections between all domains.
To facilitate a Hub-and-Spoke approach with XMPP domains, the Trunking functionality of Openfire can be used. With this functionality enabled, an Openfire instance can act as the central 'hub' in such a network. In this mode, it can create and accept server-to-server connections with each individual XMPP domain in the network, passing stanzas from one domain to another, and vice versa.
Use Case: Data Monitoring / Filtering
Openfire, in trunking mode, can be deployed as a border filtering device, to check the releasability of data that is exposed from within one network to another.
A common scenario is one where a trusted network labels messages that are exchanged with a security label (as defined in XEP-0258: Security Labels in XMPP for example) that define the confidentiality of the content of the message. An Openfire trunk can be placed between two networks of domains that each have a different security clearance. The trunking Openfire server can filter data (through a plugin), ensuring that only appropriately labelled messages are exchanged between the XMPP domains, rejecting, for example, messages labelled 'TOP SECRET' sent from an internal XMPP domain to an unrecognized or untrusted XMPP domain.
Setup
The essence in getting an Openfire instance to act as a Trunking entity in your network is to have all other XMPP domains connect to this server, when they intend to connect to another remote domain. The Trunking entity needs to be configured to accept stanzas for the target domain. This is typically achieved through DNS manipulation. It will then process the data, and pass it on to the target domain.
The server that is sending the message will attempt to establish a server-to-server connection with the target server. The sending server perform DNS lookups based on the domain name of the target server. The results of this lookup must be manipulated
in such a way that the resulting IP address is that of the trunking server. Openfire can facilitate such DNS manipulation, as it allows DNS lookups to be skipped in favor of preconfigured hard-coded values. To configure such values, the
property dnsutil.dnsOverride
can be used. Note that these changes are needed only on the server(s) that send data through the trunking server. The trunking server itself should not need them.
The expected format of the value of the dnsutil.dnsOverride
property is a comma-sparated list of {HOST,IP:PORT}
. Note that whitespace is not allowed, as shown in example 1:
To enable the trunking functionality in Openfire, the property xmpp.gateway.enabled
needs to be set to true
, and the property xmpp.gateway.domains
needs to be populated with a (comma-separated) list of XMPP domain names of remote XMPP domains that the Openfire server will forward data to.
Full example
Let us imagine three XMPP domains, each domain consisting of one Openfire server. For simplicity's sake, we assume that the fully qualified domain name of each server is equal to the XMPP domain name that it serves:
saturn.example.org
(203.0.113.2
)trunk.example.com
(198.51.100.4
)mercury.example.net
(233.252.0.6
)
The objective of this example is to allow users of the domains saturn.example.org
and mercury.example.net
to exchange XMPP stanzas without their servers creating direct connections to each-other, instead using trunk.example.com
as a gateway.
To achieve this, the following three steps are needed:
-
Openfire at
trunk.example.com
needs to be configured to allow trunking to both XMPP domains. To achieve this, it's propertyxmpp.gateway.domains
is configured to use this value:saturn.example.org,mercury.example.net
-
When a user of
saturn.example.org
sends a stanza to one of the users ofmercury.example.net
,saturn.example.org
will attempt to establish a server-to-server connection tomercury.example.net
. The objective here is to ensure thatsaturn.example.org
is made to believe that the IP address ofmercury.example.net
is198.51.100.4
, instead of its actual address233.252.0.6
. This will cause the server-to-server connection to be established totrunk.example.org
instead of tomercury.example.net
. To this end, the propertydnsutil.dnsOverride
is configured with the following value onsaturn.example.org
:{mercury.example.net,198.51.100.4:5269}
-
Typically, users will want to be able to respond to messages that they receive. To allow users of
mercury.example.net
to send back messages to users ofsaturn.example.org
, a configuration change needs to be applied onmercury.example.net
: it needs to resolve the IP address ofsaturn.example.org
to a value that equals that of the trunking server:198.51.100.4
. Similar to what was done on the other server, the propertydnsutil.dnsOverride
onmercury.example.net
is configured with the value:{saturn.example.org,198.51.100.4:5269}
These steps are all that is needed to finish the configuration in this basic example. Both servers will connect to the trunk when sending data to each-other. The trunk (which does not override DNS using the dnsutil.dnsOverride
property) will accept the stanzas
from either server, and route them to the intended target server.
Caveats
Openfire was originally not specifically designed for trunking functionality. This introduces a couple of caveats.
-
Depends on dialback (mostly)
XMPP Server-to-server connections can be authenticated in a number of ways. For trunking functionality to work, the trunk must successfully authenticate with the originating server as the target server. Openfire's Dialback authentication mechanism has been modified to support this use-case.
A different, commonly used authentication mechanism for server-to-server connections is based on TLS, using the SASL EXTERNAL mechanism to present end-entity certificates. Given the DNS trickery described earlier, an originating server will assume it is connecting to the recipient server, but instead connects to the trunking server. During TLS-based authentication, the certificate of the trunking server will be presented to the originating server, where it expects to receive the certificate of the recipient server. Usage of TLS with SASL EXTERNAL authentication typically leads to authentication failures.
-
Confusing diagnostics
Openfire's log and diagnostics can misrepresent the source and/or target addresses of data. Both servers on the endpoints of a stanza exchange will mostly appear to be communicating with each-other directly, not showing much (if any) details of the trunking server being an intermediate.