使用ejabberd搭建XMPP服务器

renyuneyun 2019年04月16日(周二) 1 mins

前两天matrix.org的服务器挂了一天,但和人交流还是要有的。然而和人的其他交流方式主要是微信,实在是太难受(不说别的,没有桌面客户端这点就足够了)。于是纠结了几分钟以后,决定自己搭一个XMPP服务器 临时用着 ,并给要联系的人也创建一个账号。

由于之前就看过相关软件,直接就选择了 ejabberd 来做后端。准备使用其他服务端软件的可以不用继续看下去了。

在网上找到一个 算是挺不错的教程 ,但其中有一些细节写得不是很好,让我配置时候走了一点弯路。做好基础搭建之后我又做了一些别的事情,都是在网上零零散散的内容。所以起心自己整理一下,顺便交代一下自己遇到的问题(万一有人知道呢)。

故而,本文会作为 教程 的补充/修改而使用,多数内容请直接参看原文。这次配置用到的服务器是 ubuntu ,源中有ejabberd等软件。下文假定软件已经安装完毕。

域名配置

我并不知道 ejabberd 是否可以配置为不使用SSL加密(我参考的 教程 什么都没说直接就开始配置SSL),但出于安全考虑,能使用SSL还是用SSL比较好。

那既然要用SSL,证书就要准备好。像我这种临时使用的,生成证书肯定是选择Let's Encrypt,免费又快捷。但Let's Encrypt需要拥有域名,不然无法签发证书,所以域名还是要配置一下的。

由于仅打算临时自己小范围使用,故而域名直接复用以前注册的那个,增加一个子域名完事。为本文叙述方便,沿用教程中的域名:jabber-gw.fmarier.org。

Let's Encrypt从一段时间以前已经被分成各个模块,而生成证书的是certbot。安装certbot及生成证书的过程不再赘述。

Let's Encrypt会在 /etc/letsencrypt/live/t.server.net/ 生成一系列文件,其中两个文件接下来会被ejabberd 用到: privkey.pemfullchain.pem 。事实上,ejabberd用到的不是这两个文件本身,而是其内容:需要将两个文件拼接成一个,交给ejabberd使用。

注意:如果要长期使用,需要考虑证书过期问题。建议参考 原作者的cron脚本 自己设定一下定时更新签名。

域名和证书本身到此就结束了,接下来进行服务端软件的配置就行。但 教程 提到在DNS处设置如下额外SRV记录(我查询得到的结论是:这些是用来进行服务自动发现的):

_xmpp-client._tcp    SRV      5 0 5222 jabber-gw.fmarier.org.
_xmpp-server._tcp    SRV      5 0 5269 jabber-gw.fmarier.org.

服务端软件(ejabberd)配置

理所当然的,ejabberd的配置文件位于 /etc/ejabberd/ 目录下( /etc/ejabberd/ejabberd.yml )。其配置文件是YAML格式的,在众多令人难受的配置格式中算是一股清流。

该文件本身已设置完毕相当多部分,多数可以保留,只有一小部分需要调整。 教程 已经给出了配置示例,我就不再赘述。

但教程中没有指出(甚至我猜作者写文的时候根本没有意识到)ejabberd的配置中允许使用 :配置文件中许多相同之处均可以用宏代替。

直接在示例配置中搜索「macro」就可以找到写宏的区域。我没有深究其语法,但比葫芦画瓢之下,所有使用宏的地方都是单引号(而所有文本都是双引号)。不知道这是语法要求还是只是为示区分。

在使用宏的基础上,配置中如下内容均可改写为宏然后引用。尤其值得注意的是, s2s_protocol_options 等项的配置默认使用了宏,所以没必要修改它们,而是应该修改宏。

ciphers: "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256"

另外不同的是(理所当然的),在有 底裤 的系统上,控制服务启动停止的是 systemctl restart ejabberd.service 等一系列命令,而非 /etc/init.d/ejabberd restart ;ubuntu的防火墙配置用的是ufw。

默认配置下,ejabberd不允许外部注册,故而需要在服务器上通过命令自己注册账号。是否允许外部注册的选项默认就在5222端口监听服务配置那。

其他模块

我的安装与教程所偏离的主要部分就在于额外模块上(模块配置在配置文件的最后一部分)。而模块的选择则是出于自己的需求:

  • 由于我需要多个客户端同时登录同一个账号,所以需要在服务器端设置 Carbons 以便各个客户端之间消息同步;
  • 由于我比较喜欢保留聊天记录,故而需要设置 MAN

Carbons通过 mod_carboncopy 完成。该模块没有额外选项,所以直接加上空配置就行。

MAN通过 mod_man 完成。该模块有一些选项,按照自己需求设置。我的方案是保存在文件中(因为临时用,数据量不大,懒得设置数据库),并且仅保存 好友 的记录。

客户端及残余问题

到上面为止,ejabberd实际上就配置完成了。我在pidgin(电脑)和conversions(手机)上用自己前面注册的账号密码登录成功,并且也可以进行聊天。

然而问题也就此浮现,并且我翻找了很久也没能解决。

半步消息同步

简单来说:我在pidgin发送的消息,在conversions上可以看到,但反过来不行。

这个事情其实相当有趣,因为就我所看到的,该消息重分发机制是由服务器完成的。换句话说,既然我在B上可以看到自己从A发送的消息,那么当我从B发送消息时A也应该收到了该事件。

然而pidgin似乎并不符合我的期待(按说这是个久经考验的软件了,应该不会有这种问题才是啊),而我又因为下一个问题而待在pidgin上。

部分客户端登录失败

前面说到我从pidgin和conversions上都可以登录成功,这证明我服务器设置完毕,账号注册正常。

然而我使用empathy登录时(是的我在那台电脑上叛逃到gnome上了,X下并没有<<30fps的事情),客户端始终提示我账号密码验证失败。

登录到服务器上,检查日志,发现说认证失败,而且还提到了OAuth2。于是我猜empathy(telepathy-gabble)用OAuth而另外两个客户端用普通的账号密码验证。因而,我去查了ejabberd设置OAuth的方法,并且对其进行配置(主要参考 官方文档 )。

然而……没用,配置过之后仍然是一样的错误。这点实在让我百思不得其解,并且随着第二天matrix.org的恢复我也就没深究了……在过了一段时间(几天)之后再测试,该问题消失。所以推测OAuth需要在DNS那边做相应设置(但我没细查)。

小结

嘛……简单来说就是我按照人家的教程,配置了ejabberd。过程实际上挺顺理成章的,而且配置下来基本能用。

但由于一些我不知道的原因,似乎仍有部分地方有奇怪的表现。如果哪位知道,还望不吝赐教。


您可以在Hypothesis上的該群組內進行評論,或使用下面的Disqus評論。