xmlperlxmpptls1.2ejabberd

XMPP connection fails using perl client and ejabberd/ecs container


I am using the docker-ejabberd/ecs container as a XMPP server and the Net::XMPP perl client My ejabberd.yml looks like this:


hosts:
  - jabber-gw.foobar.me

loglevel: debug

ca_file: /etc/ssl/certs/ca-certificates.crt

acme:
  ca_url: https://ca.foobar.local:8000/acme/acme/directory
  auto: false
  cert_type: rsa

listen:
  -
    port: 5222
    ip: "0.0.0.0"
    module: ejabberd_c2s
    max_stanza_size: 65536
    shaper: c2s_shaper
    access: c2s
    starttls_required: true
  -
    port: 5223
    ip: "0.0.0.0"
    tls: true
    module: ejabberd_c2s
    shaper: c2s_shaper
    access: c2s
    starttls_required: true
  -
    port: 5269
    ip: "0.0.0.0"
    module: ejabberd_s2s_in
    max_stanza_size: 65536

  -
    port: 5443
    ip: "0.0.0.0"
    module: ejabberd_http
    tls: true
    request_handlers:
      /admin: ejabberd_web_admin
      /api: mod_http_api
      /bosh: mod_bosh
      /captcha: ejabberd_captcha
      /upload: mod_http_upload
      /ws: ejabberd_http_ws
  -
    port: 5280
    ip: "0.0.0.0"
    module: ejabberd_http
    request_handlers:
      /admin: ejabberd_web_admin
      /.well-known/acme-challenge: ejabberd_acme
  -
    port: 3478
    ip: "0.0.0.0"
    transport: udp
    module: ejabberd_stun
    use_turn: true
    ## The server's public IPv4 address:
    # turn_ipv4_address: "203.0.113.3"
    ## The server's public IPv6 address:
    # turn_ipv6_address: "2001:db8::3"
  -
    port: 1883
    ip: "0.0.0.0"
    module: mod_mqtt
    backlog: 1000

s2s_use_starttls: optional

acl:
  local:
    user_regexp: ""
  loopback:
    ip:
      - 127.0.0.0/8
      - ::1/128

My ejabberd client perl code looks like this:


#!/usr/bin/perl

use strict;
use warnings;
use Net::XMPP qw( Client );

if ($#ARGV < 4)
{
    print "\nperl client.pl <server> <port> <username> <password> <resource> \n\n";
    exit(0);
}

my $server = $ARGV[0];
my $port = $ARGV[1];
my $username = $ARGV[2];
my $password = $ARGV[3];
my $resource = $ARGV[4];


$SIG{HUP} = \&Stop;
$SIG{KILL} = \&Stop;
$SIG{TERM} = \&Stop;
$SIG{INT} = \&Stop;

my $Connection = new Net::XMPP::Client(
                                debug => "stdout",
                                debuglevel  => 2
                                );

$Connection->SetCallBacks(message=>\&InMessage,
                          presence=>\&InPresence,
                          iq=>\&InIQ);

my $status = $Connection->Connect(hostname=>$server,
                                  port=>$port,
                                  tls=>1,
                                  srv=>"jabber-gw.foobar.me",
                                  ssl_ca_path=>"/etc/ssl/certs/"
                                );

if (!(defined($status)))
{
    print "ERROR:  Jabber server is down or connection was not allowed.\n";
    print "        ($!)\n";
    exit(0);
}

my @result = $Connection->AuthSend(username=>$username,
                                   password=>$password,
                                   resource=>$resource);

if ($result[0] ne "ok")
{
    print "ERROR: Authorization failed: $result[0] - $result[1]\n";
    exit(0);
}

print "Logged in to $server:$port...\n";

$Connection->RosterGet();

print "Getting Roster to tell server to send presence info...\n";

$Connection->PresenceSend();

print "Sending presence to tell world that we are logged in...\n";

while(defined($Connection->Process())) { }

print "ERROR: The connection was killed...\n";

exit(0);


sub Stop
{
    print "Exiting...\n";
    $Connection->Disconnect();
    exit(0);
}

I can successfully obtain an ACME cert for my host, then add the ca root cert to the clients ssl_ca_path. I then register the client on the server with ejabberdclt instructions. When i try to connect the client to the server, i see **Nodeprep failed **in the server logs:


2022-11-28 05:35:44.211915+00:00 [info] (<0.974.0>) Accepted connection 192.168.11.19:44198 -> 192.168.32.4:5222
2022-11-28 05:35:44.212589+00:00 [notice] (tcp|<0.974.0>) Received XML on stream = <<"<?xml version='1.0'?><stream:stream version='1.0' xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client' to='jabber-gw.foobar.me' from='OMVonHP.foobar.me' xml:lang='en' >">>
..
omitted
..
2022-11-28 05:35:44.310551+00:00 [notice] (tls|<0.974.0>) Received XML on stream = <<"<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'></response>">>
2022-11-28 05:35:44.310855+00:00 [debug] Running hook c2s_handle_recv: mod_stream_mgmt:c2s_handle_recv/3
2022-11-28 05:35:44.311055+00:00 [debug] Running hook c2s_auth_result: ejabberd_c2s:process_auth_result/3
2022-11-28 05:35:44.311249+00:00 [warning] (tls|<0.974.0>) Failed c2s DIGEST-MD5 authentication from 192.168.11.19: Nodeprep failed
2022-11-28 05:35:44.311422+00:00 [debug] Running hook c2s_auth_result: mod_fail2ban:c2s_auth_result/3
2022-11-28 05:35:44.311667+00:00 [notice] (tls|<0.974.0>) Send XML on stream = <<"<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><not-authorized/><text xml:lang='en'>Nodeprep failed</text></failure>">>
2022-11-28 05:35:44.311953+00:00 [debug] Running hook c2s_handle_send: mod_push:c2s_stanza/3
2022-11-28 05:35:44.314781+00:00 [debug] Running hook c2s_terminated: mod_pubsub:on_user_offline/2
2022-11-28 05:35:44.315136+00:00 [debug] Running hook c2s_terminated: ejabberd_c2s:process_terminated/2
2022-11-28 05:35:44.315395+00:00 [notice] (tls|<0.974.0>) Send XML on stream = <<"</stream:stream>">>


and in the client logs:

DMyODMwZg==)
XML::Stream: Node: _handle_close: sid(6607014926489030516) sax(XML::Stream::Parser=HASH(0x55e0c0b3e700)) tag(challenge)
XML::Stream: Node: _handle_close: check( 0 )
XML::Stream: Node: _handle_close: check2( -1 )
XML::Stream: Send: (<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'></response>)
XML::Stream: Process: block(0)
XMPP::Conn: AuthSASL: haven't authed yet... let's wait.
XMPP::Conn: Process: timeout(1)
XML::Stream: Read: buff(<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><not-authorized/><text xml:lang='en'>Nodeprep failed</text></failure>)

XMPP::Conn: AuthSASL: Authentication failed.
ERROR: Authorization failed: error - not-authorized

I cant find anywhere what Nodeprep failed means? Would appreciate some help thanks.


Solution

  • OK, it's taken me two and a half days but i have a workaround. I've worked out it's failing whilst the client is using DIGEST-MD5 sasl authentication mechanism (likely cos the NET::XMPP library hasn't been refreshed in many years). I discovered here that you can force the server to disable sasl mechanisms offered to the client, so i added:

    disable_sasl_mechanisms: DIGEST-MD5
    

    to my ejabberd.yml file which forced plain auth - not ideal but in my case i am using TLS and certs so i can live with it. With plain auth my client connects fine without Nodeprep failures.