XMPP SRV Records Problem

I have setup ejabberd 17.12 server in AWS EC2 ubuntu.  Normally EC2 provides public DNSin format ec2-35-154-2-226.ap-south-1.compute.amazonaws.com . when I setup server with this host then everything is working fine. But I wanted to have xmpp server reachable with my demain. I have been struggling to make my EC2 ejabberd server available to outside world but still in vain.

My domain:

kaiseapp.com

What I wanted is:

xmpp.kaiseapp.com

SRV Records:

I setup below DNS records:

SRVRecords

ejabberd config:

hosts:
 - "xmpp.kaiseapp.com"
 
acl:
admin:
 user:
 - "admin": "xmpp.kaiseapp.com"

host_config:
 "xmpp.kaiseapp.com":
 acl:
 admin:
 user:
 - "admin@xmpp.kaiseapp.com"

bind:

root@:~# cat /etc/bind/db.local
;
; BIND data file for local loopback interface
;
$TTL 604800
@ IN SOA localhost. root.localhost. (
 2 ; Serial
 604800 ; Refresh
 86400 ; Retry
 2419200 ; Expire
 604800 ) ; Negative Cache TTL
;
@ IN NS localhost.
@ IN A 127.0.0.1
@ IN AAAA ::1
xmpp.kaiseapp.com IN CNAME ec2-35-154-2-226.ap-south-1.compute.amazonaws.com
_xmpp-client._tcp.kaiseapp.com 86400 IN SRV 5 0 5222 xmpp.kaiseapp.com
_xmpp-server._tcp.kaiseapp.com 86400 IN SRV 5 0 5269 xmpp.kaiseapp.com

dig and host output:

ejabberd@:/usr/local/var$ dig _xmpp-client._tcp.kaiseapp.com SRV

; <<>> DiG 9.10.3-P4-Ubuntu <<>> _xmpp-client._tcp.kaiseapp.com SRV
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 42561
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;_xmpp-client._tcp.kaiseapp.com. IN SRV

;; Query time: 2153 msec
;; SERVER: 172.31.0.2#53(172.31.0.2)
;; WHEN: Sat Jan 13 01:29:52 UTC 2018
;; MSG SIZE rcvd: 59

ejabberd@:/usr/local/var$ dig _xmpp-server._tcp.kaiseapp.com SRV

; <<>> DiG 9.10.3-P4-Ubuntu <<>> _xmpp-server._tcp.kaiseapp.com SRV
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 50223
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;_xmpp-server._tcp.kaiseapp.com. IN SRV

;; Query time: 2981 msec
;; SERVER: 172.31.0.2#53(172.31.0.2)
;; WHEN: Sat Jan 13 01:30:08 UTC 2018
;; MSG SIZE rcvd: 59

root@:~# host -t SRV _xmpp-client._tcp.xmpp.kaiseapp.com
Host _xmpp-client._tcp.xmpp.kaiseapp.com not found: 2(SERVFAIL)
root@:~# host -t SRV _xmpp-server._tcp.xmpp.kaiseapp.com
;; connection timed out; no servers could be reached

 

 

 

Advertisements

Error – Fixes

problem1: unexpected event from receiver: closed; xmlstreamstart was expected

Ejabberd logs:

2018-01-06 15:33:30.849 [debug] <0.26111.2>@ejabberd_receiver:handle_info:196 TLS error = SSL_do_handshake failed: error:140760FC:SSL routines:SSL23_GET_CLIENT_HELLO:unknown protocol
2018-01-06 15:33:30.850 [debug] <0.26112.2>@ejabberd_socket:send:216 (tls|<0.26111.2>) Send XML on stream = <<"<?xml version='1.0'?><stream:stream id='7617400729795162113' version='1.0' xml:lang='en' xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client'>">>
2018-01-06 15:33:30.850 [debug] <0.26112.2>@ejabberd_socket:send:216 (tls|<0.26111.2>) Send XML on stream = <<"</stream:stream>">>
2018-01-06 15:33:30.850 [error] <0.26112.2> unexpected event from receiver: closed; xmlstreamstart was expected
sleekxmpp logs: 
ERROR CERT: Invalid certificate trust chain. DEBUG Event triggered: session_end DEBUG Event triggered: disconnected DEBUG ==== TRANSITION connected -> disconnected ERROR Error reading from XML stream.

Solution:

  1. either correct certificate in ejabberd
  2. Otherwise for workaround, you can ignore the certificate error as following.

    At this is __init__ function

    # Discard SSL Error
    self.add_event_handler("ssl_invalid_cert", self.discard)
    
    

    And create this function

    def discard(self, event):
        return
  3. or temporarily add below code:
import ssl
xmpp.ssl_version = ssl.PROTOCOL_SSLv23

XMPP Node.js Client – Demo

root@RAMESH-LENOVO:~/xmpp-echo-bot# cat index.js
//const ddg = require('ddg')
ddg = require('ddg');
const Client = require('node-xmpp-client')
, ltx = Client.ltx
const options = {
 jid: 'bot@localhost',
 password: 'password',
 host: 'localhost',
 resource: 'echo'
}
const client = new Client(options)
client.once('online', (connectionDetails) => {
 console.log('We are connected!')
 console.log(connectionDetails)
 sendPresence()
})
const sendPresence = () => {
 const stanza = new ltx.Element('presence')
 .c('show')
 .t('available')
 console.log('Sending presence: ' + stanza.toString())
 client.send(stanza)
}
const NS_CHAT_STATE = 'http://jabber.org/protocol/chatstates'
const sendChatState = (to, state) => {
 const stanza = new ltx.Element('message', { type: 'chat', to })
 stanza.c(state, { xmlns: NS_CHAT_STATE })
 console.log('Sending chat state: ' + stanza.toString())
 client.send(stanza)
}
const handleMessage = (stanza) => {
 const query = stanza.getChildText('body')
 if (!query) return /* Not a chat message */
 const from = stanza.attr('from')
 sendChatState(from, 'active')
 sendChatState(from, 'composing')
 ddg.query(query, (error, data) => {
 result = null
 if (error) {
 result = 'Unfortunately we could not answer your request'
 } else {
 if (!data.RelatedTopics[0]) {
 result = 'Sorry, there were no results!'
 } else {
 const item = data.RelatedTopics[0]
 result = item.FirstURL + '\n' + item.Text
 }
 }
 const reply = new ltx.Element(
 'message',
 { type: 'chat', to: from }
 )
 reply.c('body').t(result)
 .up()
 .c('inactive', { xmlns: NS_CHAT_STATE })
 console.log('Sending response: ' + reply)
 client.send(reply)
 })
}
const handlePresence = (stanza) => {
 if (false === stanza.attr('subscribe')) {
 return /* We don't handle anything other than a subscribe */
 }
 const reply = new ltx.Element(
 'presence',
 { type: 'subscribed', to: stanza.attr('from') }
 )
 client.send(reply)
}
client.on('stanza', (stanza) => {
 if (true === stanza.is('message')) {
 return handleMessage(stanza)
 } else if (true === stanza.is('presence')) {
 return handlePresence(stanza)
 }
})

XMPP Python Client – Demo

root@ip-172-31-7-132:~/ramesh/SleekXmpp# cat client.py
import logging

from sleekxmpp import ClientXMPP
from sleekxmpp.exceptions import IqError, IqTimeout

class EchoBot(ClientXMPP):

def __init__(self, jid, password):
 ClientXMPP.__init__(self, jid, password)

self.add_event_handler("session_start", self.session_start)
 self.add_event_handler("message", self.message)

 # If you wanted more functionality, here's how to register plugins:
 # self.register_plugin('xep_0030') # Service Discovery
 # self.register_plugin('xep_0199') # XMPP Ping

 # Here's how to access plugins once you've registered them:
 # self['xep_0030'].add_feature('echo_demo')

 # If you are working with an OpenFire server, you will
 # need to use a different SSL version:
 # import ssl
 # self.ssl_version = ssl.PROTOCOL_SSLv3

def session_start(self, event):
 self.send_presence()
 self.get_roster()

 # Most get_*/set_* methods from plugins use Iq stanzas, which
 # can generate IqError and IqTimeout exceptions
 #
 # try:
 # self.get_roster()
 # except IqError as err:
 # logging.error('There was an error getting the roster')
 # logging.error(err.iq['error']['condition'])
 # self.disconnect()
 # except IqTimeout:
 # logging.error('Server is taking too long to respond')
 # self.disconnect()

def message(self, msg):
 if msg['type'] in ('chat', 'normal'):
 msg.reply("This is robot\n%(body)s" % msg).send()

if __name__ == '__main__':
 # Ideally use optparse or argparse to get JID,
 # password, and log level.

logging.basicConfig(level=logging.DEBUG,
 format='%(levelname)-8s %(message)s')

xmpp = EchoBot('echobot@ec2-34-208-168-55.us-west-2.compute.amazonaws.com', 'xxxxxyz')
 xmpp.connect()
 xmpp.process(block=True)