Server Dialback

Jeremie Miller

The Jabber.org Project

jeremie@jabber.org

David Waite

Jabber.com

dwaite@jabber.com

01/25/2001


This below needs to be cleaned up, checked, and reformatted yet...

Server Dialback Protocol
------------------------

Introduction:

    Dialback is a method of verifying that a connection between two servers
can be trusted. Using DNS, one server can that another server which is
connecting to it is authorized to represent a given jabber server network.
It is thus used to prevent forgery; it prevents the spoofing a particular
server name and sending false data from it. The primary reason for the
complexity here is the existance of server farms: a simple reverse DNS or IP
lookup will not work for a complex environment.

    Dialback originally went into the 1.2 server. It is not currently enforced,
so that locations with 1.0 servers will have a window of upgrade.

Vocabulary:

 - Server A : This is the originating server, the server which is attempting
       to establish a connection between the two servers (A and B)
 - Server B : This is the receiving server, which is trying to authenticate
       that Server A represents the jabber server which it claims
 - Authorative Server A : This is the authorative server, which is given when
       when a DNS lookup is performed on the server name A initially gave. For
       simple environments this will be A, in other environments this could
       be a separate machine in A's network.

Overview:

    To briefly summarize the order of events in dialback:

        Server A establishes a connection to Server B
        Server A sends a 'key' value over the connection to B
        Server B establishes a connection to Authorative Server A
        Server B sends the same 'key' value to Authorative Server A
        Authoritive Server A responds whether the key works out to be
           Valid or Invalid
        Server B tells Server A whether they are authenticated or not

Implementation:

    The traffic sent between the machines is as follows:

        1. Server A establishes connection to B (Conn 1)

        2. Server A sends a stream header to B over Conn 1:

           <stream:stream xmlns:stream='http://etherx.jabber.org/streams'
                          xmlns='jabber:server' to='Server B' from='Server A'
                          xmlns:db='jabber:server:dialback'>

           The xmlns:db actually indicates to server B that server A supports
           dialback at all.

        2. Server B sends a stream header back to Server A over Conn 1:

           <stream:stream xmlns:stream='http://etherx.jabber.org/streams'
                          xmlns='jabber:server' from='Server B' to='Server A'
                          xmlns:db='jabber:server:dialback' id='457F9224A0...'>

        3. Server A sends a dialback key to Server B over Conn 1:

           <db:result to='Server B' from='Server A'>98AF014EDC0...</db:result>

           Note that this key is not even examined by Server B; it does not
           keep information on Server A between sessions.

        4. Server B now establishes a connection back to Server A, getting the
           Authorative Server A (Conn 2)

        5. Server B sends Authorative Server A a stream header on Conn 2:

           <stream:stream xmlns:stream='http://etherx.jabber.org/streams'
                          xmlns='jabber:server' from='Server B' to='Server A'
                          xmlns:db='jabber:server:dialback'>

        6. Authorative Server A sends Server B a stream header on Conn 2:

           <stream:stream xmlns:stream='http://etherx.jabber.org/streams'
                          xmlns='jabber:server' to='Server B' from='Server A'
                          xmlns:db='jabber:server:dialback' id='1251A342B...'>

           Note the presence of the id attribute: this will be explained
           further down.

        7. Server B sends Authorative Server A a packet on Conn 2 indicating
           it wants wants Authorative Server A to verify a key:

           <db:verify from='Server B' to='Server A' 
                      id='457F9224A0...'>98AF014EDC0...</db:verify>
           
           Passed here are the server names, the original identifier from
           Server B's stream header to Server A in step 2, and the key
           Server A gave Server B in step 3.

           Based on this information and shared secret information within the
           'Server A' network, the key is verified. The key generation
           technique used by the jabber.org 1.2 and 1.4 server uses a
           SHA1-hashed concatenation of a subset of this information, but the
           key is private to the servers making up the Server A network: any
           verifiable method can be used to generate the key.

        8. Authorative Server A sends a packet back to Server B over Conn 2
           indicating whether the key was valid or invalid:

           <db:result from='Server A' to='Server B' type='valid'
                      id='457F9224A0...'/>

              or

           <db:result from='Server A' to='Server B' type='invalid'
                      id='457F9224A0...'/>

        9. Server B informs Server A of the result over Conn 1:

           <db:result from='Server B' to='Server A' type='valid'/>

           At this point the connection has either been validated via a
           type='valid', or reported as invalid. Once the connection is
           validated, data can be sent over Conn 1 and read by Server B;
           before that, packets are dropped.

    There is a small caveat which makes the above considerably harder to follow.
When Server B and Authorative Server A are talking, Server B has the option of
not only sending the db:verify request over, but sending a db:result over with
its own key. After this, Authorative Server A would establish a connection with
Authorative Server B to conduct the dialback again, this time in reverse (so
that Server B can conduct server to server communication with Server A).

    The reason that Server B needs to do this is that s2s requires two sockets
between servers. Remember again that the networks can be complicated server
farms - there could be one authorative jabber server for handling s2s traffic,
and this would need to be the one that Server B communicates with, not the
Server A which established the connection