Enterprise Jabber server: catch up and overtake Google

    I think everyone knows about Google Apps . This is a great service for organizing mail and teamwork within the company. However, it has a couple of small such shortcomings: it is provided as is firstly, and all your corporate documentation, mail and correspondence when using Google Apps will be stored on Google servers.

    As a result, most often serious firms choose the difficult path - to support all the necessary services on their own servers. This way, of course, gives a lot of advantages. The company’s system administrator will be able to configure anything and any way. However, there is one significant drawback: if Google has everything configured and connected together, then you have to configure everything manually. Plus, you are unlikely to be able to provide your system with the same beautiful and convenient web interface.

    However, as practice shows, it’s easy to deploy a flexible and powerful infrastructure for a company without the help of Google. Under the cat, I’ll tell you how to integrate the XMPP server with the mail system, so that in the end it turns out much better than Google.

    Mail server


    First you need a mail server. The smart choice for the MTA is Postfix , as one of the most modular, flexible and yet reliable. To deliver mail to end recipients without options, you need an IMAP server, which I use Dovecot for .

    Docotmakes it easy to use almost any standard storage as a user base. For example, I use AD. In addition, Dovecot provides third-party applications with the ability to log in through themselves, in particular, Postfix can do this. Thus, a very convenient scheme is obtained: Dovecot is responsible for communicating with the user database, and all other components of the system simply turn to it for authorization verification. The advantage is obvious: you wanted to change the database (for example, abandon AD in favor of OpenLDAP) - you do not need to reconfigure anything, just send Dovecot to the new storage.

    How to configure a bunch of Dovecot + Postfixwritten in the documentation for these programs. As a result of the setup, I personally acquired SMTP and IMAP servers, which are authorized on which users by domain login / password. By the way, Dovecot and Postfix have very good documentation - this is also an important advantage of these products. Therefore, I’m sure that there shouldn’t be any problems setting up this bunch.

    Jabber server


    The only thing left to do is to fasten the server to the existing Jabber mail system. To do this is ridiculously elementary. First you need to install ejabberd . Why him? If only because it is the most flexible. A lot of articles have been written about the rich capabilities of this product, so I'll go straight to organizing ejabberd authorization through Dovecot. Fortunately, ejabberd supports external authorization , and all you need to do is write a script to validate user data through Dovecot.

    A small digression: external authorization mechanisms through Dovecot work through two UNIX sockets created by Dovecot. The parameters of these sockets are specified in the Dovecot config, more details about them can be found on the official wiki .

    Having rummaged a bit on the Internet I found such a fruit: http://search.cpan.org/~sasha/Authen-SASL-Authd-0.04/lib/Authen/SASL/Authd.pm

    Brazenly poking code from it and adding the necessary for ejabberd The behavior got the final version:

    #!/usr/bin/perl

    use 5.010;
    use IO::Socket::UNIX;
    use IO::Select;
    use MIME::Base64 qw(encode_base64);

    # Сокеты Dovecot
    $dovecot_auth_master = '/var/run/dovecot/auth-master';
    $dovecot_auth_client = '/var/spool/postfix/private/auth-client';

    sub read_until {
            my ($sock, $re, $timeout) = @_;
            my $sel = new IO::Select($sock);
            my $result = '';
            while ($result !~ /$re/m) {
                    $sel->can_read($timeout) or die "Timed out while waiting for response";
                    defined recv($sock, my $buf, 256, 0) or die 'Error while reading response';
                    $result .= $buf;
            }
            return $result;
    }

    sub dovecot_auth {

            my ($login, $passwd) = @_;

            utf8::encode($login);
            utf8::encode($passwd);
           
            my $base64 = encode_base64("\0$login\0$passwd",'');

            my $service = "ejabberd";
            my $timeout = 3;

            my $sock = new IO::Socket::UNIX(Type => SOCK_STREAM, Peer => $dovecot_auth_client) or die;

            my $resp = read_until($sock,'DONE',$timeout);
           
            die unless $resp =~ /^VERSION\t1\t\d+$/m;
            die unless $resp =~ /^MECH\tPLAIN/m;
                   
            $sock->send("VERSION\t1\t0\nCPID\t$$\nAUTH\t1\tPLAIN\tservice=$service\tsecured\tresp=$base64\n") or die;

            $resp = read_until($sock,'\n',$timeout);

            $sock->close;
           
            return $resp =~ /OK/;
    }

    sub dovecot_user {
           
            my $login = shift @_;
           
            utf8::encode($login);
           
            my $service = "ejabberd";
            my $timeout = 3;
           
            my $sock = new IO::Socket::UNIX(Type => SOCK_STREAM, Peer => $dovecot_auth_master) or die;
           
            my $resp = read_until($sock,'VERSION',$timeout);
           
            die unless $resp =~ /^VERSION\t1\t\d+$/m;
           
            $sock->send("VERSION\t1\t0\nUSER\t1\t$login\tservice=$service\tsecured\n") or die;
           
            $resp = read_until($sock,'\n',$timeout);

            $sock->close;
           
            return $resp =~ /USER/;
    }

    # Reading information from ejabberd
    while(1) {
            my $nread = sysread STDIN, my $buf, 2;
            unless ($nread == 2) { exit }
            my $len = unpack "n", $buf;
            $nread = sysread STDIN, $buf, $len;
           
            my ($op,$user,$domain,$passwd) = split /:/, $buf;

            # Filter dangerous characters
            $user =~ s/[."\n\r'\$`]//g;
            $passwd =~ s/[."\n\r'\$`]//g;
            $domain =~ s/[."\n\r'\$`]//g;
           
            my $result = 0;
            if ($op =~ /auth/i) {
                    $result = dovecot_auth($user, $passwd) ? 1 : 0;
            } elsif ($op =~ /isuser/i) {
                    $result = dovecot_user($user) ? 1 : 0;
            }
           
            my $out = pack "nn", 2, $result;
            syswrite STDOUT, $out;
    }

    A short note: the source module from CPAN is currently unlikely to work. For correct interaction with Dovecot, when calling the function encode_base64, you must specify an empty string as the second argument. In the above script, this is of course taken into account.

    It is worth noting that for authorization through Dovecot, the ejabberd process must have read and write permissions to the Dovecot authorization sockets. Ejabberd works on behalf of the user ejabberd, which, by a strange coincidence, is a member of the ejabberd group. Thus, do not forget to give rw rights for this user (or group) to both Dovecot sockets and to the directories in which they are located (for some reason they often forget about the last item).

    It remains to add our script to the ejabberd config:
    {auth_method, external}.
    {extauth_program, "/etc/ejabberd/auth.pl"}.

    Actually, this is where the substantive part ends. Now, in addition to mail, users will be able to log in under their domain logins also in Jabber. And if you didn’t distort much when setting up the mail system, then each user’s JID and email will match and look like username@domain.com.

    However, it remains to catch up and overtake Google. Well, this is very simple. It is a completely standard way to include the necessary functions in ejabberd. Here are the most interesting features from my point of view:

    • Conferences , they are also MUC. The standard module mod_muc is responsible for their support ; you only need to configure the desired default parameters.
    • Logging conferences . The mod_muc_log module is responsible for this . He puts all the conference logs in one folder in the form of HTML files, all that remains is to set Apache on this folder and allow access to the received resource only from the local network.
    • Logging personal correspondence . To enable this feature, you will need to reinstall the mod_log_chat module , which will put all the logs in one folder again, in the form of HTML files. Then you can write a simple script that will periodically scan this folder and send the necessary files to the right email addresses. Thus, we get functionality similar to Google.
    • Common roasters . An extremely useful opportunity within the company. Mod_shared_rosters is responsible for it . Allows you to flexibly manage user rosters, adding entire groups to them.
    • Support for offline messages . Just don't turn it off ( mod_offline if that)
    • Transports . I think this item does not need comments. You can provide your employees with an easy way to communicate through any existing IM network.

    Just in case, I will draw your attention to the fact that since Since we set up an authorization system combined with mail (and in my case even with AD), then everything related to registration on a Jabber server should be turned off. For example, the same mod_register. Just so that the eyes do not callus.

    Summary


    So, with a simple script, you can connect mail and Jabber together, while leaving yourself virtually unlimited freedom to configure everything and everything within the framework of the products used. And since some of the most functional, flexible and reliable tools were used in their fields, in fact, it turns out to be almost the most powerful system of all possible within the framework of the task (mail + IM for corporate communication). No integrated solution like Exchange, and even less so Google Apps, of course, and close can provide such functionality. Moreover, from the point of view of the user, the resulting system is absolutely transparent and as easy to use as possible, and from the point of view of the administrator, too. Unless the administrator needs to understand everything during configuration (and configure everything correctly!),

    PS If anyone is interested, I can tell you how to squeeze out a lot of interesting things from the Dovecot + Postfix bunch (IMAP ACL, admin direct access to any mailbox from any client, mailing lists, public folders, subscriptions, delegation of rights by users etc) and how organize flexible configuration of any parameters of the Thunderbird email client through the server, saving users from the need (and if desired, the ability) to change anything in their client.

    Also popular now: