使用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評論。