Matrix Gateway: Messages from XMPP to Matrix are not delivered (only Matrix → XMPP works)
Environment
- ejabberd version: latest docker image (2025-08-22 build)
- Transport:
mod_matrix_gw - OS: Linux (Ubuntu)
- Installed from: source
Configuration (only if needed): grep -Ev '^$|^\s*#' ejabberd.yml
hosts:
- mydomain.tld
host_config:
mydomain.tld:
auth_method: [ldap]
ldap_servers:
- lldap
ldap_port: 3890
ldap_uids:
- uid
ldap_rootdn: "uid=binduser,ou=people,dc=mydomain,dc=tld"
ldap_password: "password123"
ldap_base: "ou=people,dc=mydomain,dc=tld"
loglevel: debug
define_macro:
TLS_CIPHERS: ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
TLS_OPTIONS:
- no_sslv3
- no_tlsv1
- no_tlsv1_1
- cipher_server_preference
- no_compression
c2s_ciphers: TLS_CIPHERS
s2s_ciphers: TLS_CIPHERS
c2s_protocol_options: TLS_OPTIONS
s2s_protocol_options: TLS_OPTIONS
s2s_use_starttls: required
disable_sasl_mechanisms:
- digest-md5
- X-OAUTH2
certfiles:
- /etc/ssl/certificates/*ydomain.tld/*.crt
- /etc/ssl/certificates/*ydomain.tld/*.key
listen:
-
port: 5222
ip: "::"
module: ejabberd_c2s
max_stanza_size: 262144
shaper: c2s_shaper
access: c2s
starttls_required: true
protocol_options: TLS_OPTIONS
-
port: 5223
ip: "::"
module: ejabberd_c2s
max_stanza_size: 262144
shaper: c2s_shaper
access: c2s
tls: true
protocol_options: TLS_OPTIONS
-
port: 5269
ip: "::"
module: ejabberd_s2s_in
max_stanza_size: 524288
shaper: s2s_shaper
-
port: 5270
ip: "::"
module: ejabberd_s2s_in
max_stanza_size: 524288
shaper: s2s_shaper
tls: true
protocol_options: TLS_OPTIONS
-
port: 5443
ip: "::"
module: ejabberd_http
tls: true
protocol_options: TLS_OPTIONS
request_handlers:
/conversejs: mod_conversejs
/admin: ejabberd_web_admin
/api: mod_http_api
/http-bind: mod_bosh
/captcha: ejabberd_captcha
/upload: mod_http_upload
/ws: ejabberd_http_ws
/.well-known/host-meta: mod_host_meta
/.well-known/host-meta.json: mod_host_meta
-
port: 5280
ip: "::"
module: ejabberd_http
request_handlers:
/.well-known/acme-challenge: ejabberd_acme
-
port: 3478
ip: "::"
transport: udp
module: ejabberd_stun
use_turn: true
turn_min_port: 49152
turn_max_port: 65535
turn_ipv4_address: "my_ipv4"
turn_ipv6_address: "my_ipv6"
-
port: 5349
transport: tcp
ip: "::"
module: ejabberd_stun
use_turn: true
tls: true
-
port: 5347
ip: "::"
module: ejabberd_service
access: all
hosts:
irc.mydomain.tld:
password: password123
-
port: 5348
ip: "::"
module: ejabberd_service
access: local
hosts:
irc-bridge.mydomain.tld:
password: password123
-
port: 8448 # Matrix federation
module: ejabberd_http
tls: true
request_handlers:
"/_matrix": mod_matrix_gw
acme:
auto: false
ca_url: https://acme-staging-v02.api.letsencrypt.org/directory
acl:
local:
user_regexp: ""
loopback:
ip:
- 127.0.0.0/8
- ::1/128
admin:
user: admin
s2s_access: s2s
access_rules:
local:
allow: local
c2s:
deny: blocked
allow: all
s2s:
- allow # to allow Matrix federation
announce:
allow: admin
configure:
allow: admin
muc_create:
allow: local
pubsub_createnode:
allow: local
trusted_network:
allow: loopback
api_permissions:
"console commands":
from: ejabberd_ctl
who: all
what: "*"
"webadmin commands":
from: ejabberd_web_admin
who: admin
what: "*"
"admin access":
who:
access:
allow:
- acl: loopback
- acl: admin
oauth:
scope: "ejabberd:admin"
access:
allow:
- acl: loopback
- acl: admin
what:
- "*"
- "!stop"
- "!start"
"public commands":
who:
ip: 127.0.0.1/8
what:
- status
- connected_users_number
shaper:
normal:
rate: 3000
burst_size: 20000
fast: 100000
shaper_rules:
max_user_sessions: 10
max_user_offline_messages:
5000: admin
100: all
c2s_shaper:
none: admin
normal: all
s2s_shaper: fast
modules:
mod_adhoc: {}
mod_admin_extra: {}
mod_announce:
access: announce
mod_avatar: {}
mod_blocking: {}
mod_bosh: {}
mod_caps: {}
mod_carboncopy: {}
mod_client_state: {}
mod_configure: {}
mod_conversejs:
conversejs_options:
locked_domain: "@HOST@"
message_archiving: always
mod_disco:
server_info:
- modules: all
name: abuse-addresses
urls:
- "mailto:[email protected]"
- modules: all
name: support-addresses
urls:
- "mailto:[email protected]"
- modules: all
name: admin-addresses
urls:
- "mailto:[email protected]"
mod_fail2ban: {}
mod_host_meta:
bosh_service_url: "https://xmpp.@HOST@/http-bind"
websocket_url: "wss://xmpp.@HOST@/ws"
mod_http_api: {}
mod_http_upload:
put_url: https://xmpp.@HOST@/upload
docroot: /var/www/upload
custom_headers:
"Access-Control-Allow-Origin": "*"
"Access-Control-Allow-Methods": "GET,HEAD,PUT,OPTIONS"
"Access-Control-Allow-Headers": "Content-Type"
mod_last: {}
mod_mam:
db_type: sql
assume_mam_usage: true
default: always
mod_matrix_gw:
key_name: "key1"
key: "key_matrix"
matrix_id_as_jid: true
mod_muc:
host: grupo.@HOST@
access:
- allow
access_admin:
- allow: admin
access_create: muc_create
access_persistent: muc_create
access_mam:
- allow
default_room_options:
mam: true
allow_subscription: true
mod_muc_admin: {}
mod_muc_occupantid: {}
mod_offline:
access_max_user_messages: max_user_offline_messages
mod_ping: {}
mod_privacy: {}
mod_private: {}
mod_proxy65:
access: local
max_connections: 5
mod_pubsub:
access_createnode: pubsub_createnode
plugins:
- flat
- pep
force_node_config:
storage:bookmarks:
access_model: whitelist
mod_push: {}
mod_push_keepalive: {}
mod_roster:
versioning: true
mod_s2s_dialback: {}
mod_shared_roster: {}
mod_stream_mgmt:
resend_on_timeout: if_offline
mod_stun_disco: {}
mod_vcard: {}
mod_vcard_xupdate: {}
mod_version:
show_os: false
sql_type: pgsql
sql_server: "postgres"
sql_database: "ejabberd"
sql_username: "ejabberd"
sql_password: "password123"
default_db: sql
Errors from error.log/crash.log
No errors (excerpt)
docker compose logs ejabberd
2025-08-22 21:06:44.855 [notice] (tls|<0.731.0>) Received XML on stream = "<message ...>"
2025-08-22 21:06:44.925 [debug] hook module = mod_matrix_gw
2025-08-22 21:06:44.927 [debug] Route: [email protected]
2025-08-22 21:06:44.933 [debug] (s2s|<0.741.0>) Send XML on stream = "<message to='[email protected]' ...>"
There are no errors or warnings in the ejabberd logs, and the stanza appears to be forwarded correctly, but the Matrix side never receives it.
Bug description
I am testing the mod_matrix_gw in the latest ejabberd release (docker image). I can successfully send messages from Matrix to my XMPP user, but the reverse direction does not work: messages from XMPP to Matrix are never received on the Matrix side.
Expected Behavior
- When my XMPP user sends a message to a Matrix contact (via the ejabberd Matrix Gateway), the Matrix user should receive the message.
Actual Behavior
-
The XMPP user’s message is processed by ejabberd normally:
- The stanza is received and parsed.
- It is archived in MAM.
- It is duplicated to the other connected XMPP resource (carbon copy).
- ejabberd logs show the stanza routed through
mod_matrix_gwand forwarded tomatrix.orgvia s2s.
-
But the Matrix user never receives the message.
Steps to Reproduce
- Configure ejabberd with
mod_matrix_gw. - Connect an XMPP client to ejabberd.
- Add a Matrix user as a contact and send messages both ways.
- Observe that only Matrix → XMPP works, not XMPP → Matrix.
Notes
- TLS and s2s federation are working (messages to XMPP arrive fine).
- The problem is specifically with delivery from XMPP → Matrix.
I have the opposite behaviour in some chats, where mesages XMPP -> Matrix work fine, but not Matrix -> XMPP.
Same cause perhaps?
I have the opposite behaviour in some chats, where mesages XMPP -> Matrix work fine, but not Matrix -> XMPP.
Same cause perhaps?
Maybe. This is my reverse proxy configuration in case that matters:
Caddyfile
mydomain.tld {
handle /.well-known/matrix/server {
header Content-Type application/json
respond `{ "m.server": "matrix.mydomain.tld:8448" }`
}
handle /_matrix* {
reverse_proxy localhost:8448 {
transport http {
tls_insecure_skip_verify
}
header_up Host {host}
}
}
}
matrix.mydomain.tld {
handle /_matrix* {
reverse_proxy localhost:8448 {
transport http {
tls_insecure_skip_verify
}
header_up Host {host}
}
}
}
I have the opposite behaviour in some chats, where mesages XMPP -> Matrix work fine, but not Matrix -> XMPP.
Same cause perhaps?
Would you mind sharing what you are doing differently?
When using matrix_id_as_jid: true option and sending something to [email protected], ejabberd first tries to connect to the server using XMPP, and when it fails tries to use Matrix. But apparently matrix.org has an XMPP server or gateway:
_xmpp-server._tcp.matrix.org has SRV record 0 5 5269 lethe.matrix.org.
and it gets your messages.
To avoid it you can try to reject TCP packets going to lethe.matrix.org:5269.
And please check if the problem appears with other Matrix servers.
Is there a recommended way to avoid these unintended XMPP connections? Should it be blocked via firewall (iptables/nftables), or can this be configured inside ejabberd (ACL / s2s_access)?
On September 29, 2025 11:01:01 GMT-03:00, Alexey Shchepin @.***> wrote:
alexeyshch left a comment (processone/ejabberd#4442)
When using
matrix_id_as_jid: trueoption and sending something to @.***, ejabberd first tries to connect to the server using XMPP, and when it fails tries to use Matrix. But apparentlymatrix.org` has an XMPP server or gateway:_xmpp-server._tcp.matrix.org has SRV record 0 5 5269 lethe.matrix.org.and it gets your messages.
To avoid it you can try to reject TCP packets going to lethe.matrix.org:5269.
And please check if the problem appears with other Matrix servers.
-- Reply to this email directly or view it on GitHub: https://github.com/processone/ejabberd/issues/4442#issuecomment-3347141539 You are receiving this because you authored the thread.
Message ID: @.***>
Anyway I've set matrix_id_as_jid: false now and using user%<[email protected]>.tld still got the same behavior, I can only receive from matrix.org, never send.
That would seem like expected behavior as the s2s requests would still end up on the same IP, no?
But did you check with Matrix servers other than Matrix.org? Does it work there?
I will try, do you know another free matrix server? I have account only in matrix.org
Did it in the server envs.net, still can't join:
The Matrix Server seems to be able to send
Sorry, not very familiar with Matrix servers, maybe https://tchncs.de/en/ ?
But not being able to join is a totally different issue compared to one way message passing only, no?
I will try this server too.
From a user perspective looks the same, the matrix side seems to be able to send, but from XMPP I can't even join the room. I would appreciate instructions for giving better information about the issue.
@poVoq Thanks! That server works!
Chatting with a tchncs.de account works as expected, super!
So the problem would be in the Matrix side in matrix.org and envs.net?
Interestingly https://connect.xmpp.net/ shows an open starttls for s2s on matrix.org but not on lethe.matrix.org