Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Reverse proxy causes "Invalid signature for server ..." resulting in inability to accept invites #3294

Closed
fadenb opened this issue May 26, 2018 · 30 comments

Comments

@fadenb
Copy link

fadenb commented May 26, 2018

Description

I am unable to invite people on some servers into a chat.
In Riot I see no difference (but no one ever accepts the invite ;) )

Synapse always logs something similiar to this:

May 25 11:37:58 m00 synapse[1030]: signedjson.sign: [GET-123405] Error verifying signature
                                   Traceback (most recent call last):
                                     File "/nix/store/0b3bjqyx1lgks8ja23g1whw9mwjfc5sn-python2.7-signedjson-1.0.0/lib/python2.7/site-packages/signedjson/sign.py", line 121, in verify_signed_json
                                       verify_key.verify(message, signature)
                                     File "/nix/store/fv5ps1k1gcak9abndxm5skdqgqrzk3bp-python2.7-pynacl-1.2.1/lib/python2.7/site-packages/nacl/signing.py", line 114, in verify
                                       return nacl.bindings.crypto_sign_open(smessage, self._key)
                                     File "/nix/store/fv5ps1k1gcak9abndxm5skdqgqrzk3bp-python2.7-pynacl-1.2.1/lib/python2.7/site-packages/nacl/bindings/crypto_sign.py", line 109, in crypto_sign_open
                                       raise exc.BadSignatureError("Signature was forged or corrupt")
                                   BadSignatureError: Signature was forged or corrupt
May 25 11:37:58 m00 synapse[1030]: synapse.federation.transport.server: [GET-123405] authenticate_request failed
                                   Traceback (most recent call last):
                                     File "/nix/store/z8772byjm0gqh05rrs2084zsnjj40fic-matrix-synapse-0.28.1/lib/python2.7/site-packages/synapse/federation/transport/server.py", line 182, in new_func
                                       origin = yield authenticator.authenticate_request(request, content)
                                   SynapseError: 401: Invalid signature for server asra.gr with key ed25519:a_uGgJ

The remote side receives the invite but is unable to accept it ("unauthorized").

Federation tester did not show any issues at the time of the error for both involved servers:
https://matrix.org/federationtester/api/report?server_name=utzutzutz.net
https://matrix.org/federationtester/api/report?server_name=asra.gr

Several synapse operators seem to have the same issue. It does not seem to be related to OS or installation method.
See https://matrix.to/#/!HsxjoYRFsDtWBgDQPh:matrix.org/$1527262498154duwWE:fws.fr for some more examples.

Steps to reproduce

  • have account on affected homeserver
  • Invite user from different homeserver

Version information

  • Homeserver: utzutzutz.net (+ others, see link above)

If not matrix.org:

  • Version: 0.30.0
  • Install method: NixOS module
  • Platform: NixOS 18.03, VM, nginx reverse proxy in front of synapse
@dani
Copy link

dani commented May 26, 2018

Removing the proxy on the federation port clears the issue, so it seems related to this

@OlegGirko
Copy link
Contributor

I have the same issue.
My configuration:

  • Synapse and all relevant packages built for Fedora and installed from a repo on my OBS server.
  • Reverse proxy through Apache HTTPD, version 2.4.33, installed from Fedora repo.
  • Reverse proxy configuration:
ProxyPass /_matrix http://127.0.0.1:8008/_matrix timeout=600
ProxyPassReverse /_matrix http://127.0.0.1:8008/_matrix
  • Synapse running on port 8008 behind reverse proxy, with no_tls: True.

Synapse receives request from matrix.org.
Request headers:

Content-Length: 1455
X-Forwarded-Host: infoserver.lv
X-Forwarded-For: 83.136.249.97
Connection: Keep-Alive
User-Agent: Synapse/0.30.0-rc1 (b=matrix-org-hotfixes,4ae6080)
Host: 127.0.0.1:8008
X-Forwarded-Server: infoserver.lv
Content-Type: application/json
Authorization: X-Matrix origin=matrix.org,key="ed25519:auto",sig="ZPycrvgFKt5B9nUwDyxom4LSKivdgLxLaZM+Eo5t6yFBDQdD8wT9B+T7QD01tvhTd0fqGz787LvtZEFe9GsQCQ"

Request content (as Python string):

'{"auth_events":[["$152735895692674zWMqz:matrix.org",{"sha256":"8UObuZNGmyJ08TQ6aDiim0lAP/Xvcz3QJ4+I9cBlOc8"}],["$152735895892675Stnog:matrix.org",{"sha256":"WYqp/CKCoVHURPOosQAYaKWiQf8FIcR63SNA9zRRxZw"}],["$152735895692673mNESD:matrix.org",{"sha256":"gM4O3VPYPXIIk/W589DUu/FVY0qarC1/qIWcUr21weo"}],["$152735895992676SrVyB:matrix.org",{"sha256":"v53QKB592/sT5+vfHODuxp2H8CYzVx6EVnGuSXb3NfQ"}]],"content":{"avatar_url":"mxc://infoserver.lv/XbHFzOXJypHstVGnsFlRcSTC","displayname":"Oleg Girko","is_direct":true,"membership":"invite"},"depth":7,"event_id":"$152735895992679nRnho:matrix.org","hashes":{"sha256":"OHJZxQKKUz/GS+GoOixWUJJajvB/MxyQGFQgoayYrjE"},"membership":"invite","origin":"matrix.org","origin_server_ts":1527358959995,"prev_events":[["$152735895992678Hezxs:matrix.org",{"sha256":"27kUzkmXpFGXQub7vTwvdcP1U9PTjNzBZSoWBeYJpHM"}]],"prev_state":[],"room_id":"!TgLZRSYjbikNgCOWLA:matrix.org","sender":"@iav:matrix.org","signatures":{"matrix.org":{"ed25519:auto":"RbIga6iJjGBfC3A8Za4C6AZJ03ZHhGzXpAbO3VvOIbGOsQV+uDgGCxVZbBx7Cam9rk50nybdzcCgHxNb6XhNCA"}},"state_key":"@ol:infoserver.lv","type":"m.room.member","unsigned":{"age":549,"invite_room_state":[{"content":{"join_rule":"invite"},"sender":"@iav:matrix.org","state_key":"","type":"m.room.join_rules"},{"content":{"avatar_url":"mxc://matrix.org/kVrxVLSbutexWwcDZSXzwgZK","displayname":"iav","membership":"join"},"sender":"@iav:matrix.org","state_key":"@iav:matrix.org","type":"m.room.member"}]}}'

The same JSON object pretty printed with indentation:

{
  "origin": "matrix.org", 
  "signatures": {
    "matrix.org": {
      "ed25519:auto": "RbIga6iJjGBfC3A8Za4C6AZJ03ZHhGzXpAbO3VvOIbGOsQV+uDgGCxVZbBx7Cam9rk50nybdzcCgHxNb6XhNCA"
    }
  }, 
  "origin_server_ts": 1527358959995, 
  "sender": "@iav:matrix.org", 
  "event_id": "$152735895992679nRnho:matrix.org", 
  "prev_events": [
    [
      "$152735895992678Hezxs:matrix.org", 
      {
        "sha256": "27kUzkmXpFGXQub7vTwvdcP1U9PTjNzBZSoWBeYJpHM"
      }
    ]
  ], 
  "membership": "invite", 
  "state_key": "@ol:infoserver.lv", 
  "unsigned": {
    "age": 549, 
    "invite_room_state": [
      {
        "content": {
          "join_rule": "invite"
        }, 
        "type": "m.room.join_rules", 
        "sender": "@iav:matrix.org", 
        "state_key": ""
      }, 
      {
        "content": {
          "membership": "join", 
          "avatar_url": "mxc://matrix.org/kVrxVLSbutexWwcDZSXzwgZK", 
          "displayname": "iav"
        }, 
        "type": "m.room.member", 
        "sender": "@iav:matrix.org", 
        "state_key": "@iav:matrix.org"
      }
    ]
  }, 
  "content": {
    "membership": "invite", 
    "avatar_url": "mxc://infoserver.lv/XbHFzOXJypHstVGnsFlRcSTC", 
    "displayname": "Oleg Girko", 
    "is_direct": true
  }, 
  "depth": 7, 
  "prev_state": [], 
  "room_id": "!TgLZRSYjbikNgCOWLA:matrix.org", 
  "auth_events": [
    [
      "$152735895692674zWMqz:matrix.org", 
      {
        "sha256": "8UObuZNGmyJ08TQ6aDiim0lAP/Xvcz3QJ4+I9cBlOc8"
      }
    ], 
    [
      "$152735895892675Stnog:matrix.org", 
      {
        "sha256": "WYqp/CKCoVHURPOosQAYaKWiQf8FIcR63SNA9zRRxZw"
      }
    ], 
    [
      "$152735895692673mNESD:matrix.org", 
      {
        "sha256": "gM4O3VPYPXIIk/W589DUu/FVY0qarC1/qIWcUr21weo"
      }
    ], 
    [
      "$152735895992676SrVyB:matrix.org", 
      {
        "sha256": "v53QKB592/sT5+vfHODuxp2H8CYzVx6EVnGuSXb3NfQ"
      }
    ]
  ], 
  "hashes": {
    "sha256": "OHJZxQKKUz/GS+GoOixWUJJajvB/MxyQGFQgoayYrjE"
  }, 
  "type": "m.room.member"
}

JSON object passed to signedjson.sign.verify_signed_json function:

{'origin': 'matrix.org', 'signatures': {'matrix.org': {'ed25519:auto': 'ZPycrvgFKt5B9nUwDyxom4LSKivdgLxLaZM+Eo5t6yFBDQdD8wT9B+T7QD01tvhTd0fqGz787LvtZEFe9GsQCQ'}}, 'destination': 'infoserver.lv', 'uri': '/_matrix/federation/v1/invite/!TgLZRSYjbikNgCOWLA:matrix.org/$152735895992679nRnho:matrix.org', 'content': {'origin': 'matrix.org', 'signatures': {'matrix.org': {'ed25519:auto': 'RbIga6iJjGBfC3A8Za4C6AZJ03ZHhGzXpAbO3VvOIbGOsQV+uDgGCxVZbBx7Cam9rk50nybdzcCgHxNb6XhNCA'}}, 'origin_server_ts': 1527358959995, 'sender': '@iav:matrix.org', 'event_id': '$152735895992679nRnho:matrix.org', 'prev_events': [['$152735895992678Hezxs:matrix.org', {'sha256': '27kUzkmXpFGXQub7vTwvdcP1U9PTjNzBZSoWBeYJpHM'}]], 'membership': 'invite', 'state_key': '@ol:infoserver.lv', 'unsigned': {'age': 549, 'invite_room_state': [{'content': {'join_rule': 'invite'}, 'type': 'm.room.join_rules', 'sender': '@iav:matrix.org', 'state_key': u''}, {'content': {'membership': 'join', 'avatar_url': 'mxc://matrix.org/kVrxVLSbutexWwcDZSXzwgZK', 'displayname': 'iav'}, 'type': 'm.room.member', 'sender': '@iav:matrix.org', 'state_key': '@iav:matrix.org'}]}, 'content': {'membership': 'invite', 'avatar_url': 'mxc://infoserver.lv/XbHFzOXJypHstVGnsFlRcSTC', 'displayname': 'Oleg Girko', 'is_direct': True}, 'depth': 7, 'prev_state': [], 'room_id': '!TgLZRSYjbikNgCOWLA:matrix.org', 'auth_events': [['$152735895692674zWMqz:matrix.org', {'sha256': '8UObuZNGmyJ08TQ6aDiim0lAP/Xvcz3QJ4+I9cBlOc8'}], ['$152735895892675Stnog:matrix.org', {'sha256': 'WYqp/CKCoVHURPOosQAYaKWiQf8FIcR63SNA9zRRxZw'}], ['$152735895692673mNESD:matrix.org', {'sha256': 'gM4O3VPYPXIIk/W589DUu/FVY0qarC1/qIWcUr21weo'}], ['$152735895992676SrVyB:matrix.org', {'sha256': 'v53QKB592/sT5+vfHODuxp2H8CYzVx6EVnGuSXb3NfQ'}]], 'hashes': {'sha256': 'OHJZxQKKUz/GS+GoOixWUJJajvB/MxyQGFQgoayYrjE'}, 'type': 'm.room.member'}, 'method': 'PUT'}

The same JSON object pretty printed:

{
  "origin": "matrix.org", 
  "signatures": {
    "matrix.org": {
      "ed25519:auto": "ZPycrvgFKt5B9nUwDyxom4LSKivdgLxLaZM+Eo5t6yFBDQdD8wT9B+T7QD01tvhTd0fqGz787LvtZEFe9GsQCQ"
    }
  }, 
  "destination": "infoserver.lv", 
  "uri": "/_matrix/federation/v1/invite/!TgLZRSYjbikNgCOWLA:matrix.org/$152735895992679nRnho:matrix.org", 
  "content": {
    "origin": "matrix.org", 
    "depth": 7, 
    "signatures": {
      "matrix.org": {
        "ed25519:auto": "RbIga6iJjGBfC3A8Za4C6AZJ03ZHhGzXpAbO3VvOIbGOsQV+uDgGCxVZbBx7Cam9rk50nybdzcCgHxNb6XhNCA"
      }
    }, 
    "origin_server_ts": 1527358959995, 
    "sender": "@iav:matrix.org", 
    "event_id": "$152735895992679nRnho:matrix.org", 
    "prev_events": [
      [
        "$152735895992678Hezxs:matrix.org", 
        {
          "sha256": "27kUzkmXpFGXQub7vTwvdcP1U9PTjNzBZSoWBeYJpHM"
        }
      ]
    ], 
    "unsigned": {
      "age": 549, 
      "invite_room_state": [
        {
          "content": {
            "join_rule": "invite"
          }, 
          "type": "m.room.join_rules", 
          "sender": "@iav:matrix.org", 
          "state_key": ""
        }, 
        {
          "content": {
            "membership": "join", 
            "avatar_url": "mxc://matrix.org/kVrxVLSbutexWwcDZSXzwgZK", 
            "displayname": "iav"
          }, 
          "type": "m.room.member", 
          "sender": "@iav:matrix.org", 
          "state_key": "@iav:matrix.org"
        }
      ]
    }, 
    "state_key": "@ol:infoserver.lv", 
    "content": {
      "membership": "invite", 
      "avatar_url": "mxc://infoserver.lv/XbHFzOXJypHstVGnsFlRcSTC", 
      "displayname": "Oleg Girko", 
      "is_direct": true
    }, 
    "membership": "invite", 
    "prev_state": [], 
    "room_id": "!TgLZRSYjbikNgCOWLA:matrix.org", 
    "auth_events": [
      [
        "$152735895692674zWMqz:matrix.org", 
        {
          "sha256": "8UObuZNGmyJ08TQ6aDiim0lAP/Xvcz3QJ4+I9cBlOc8"
        }
      ], 
      [
        "$152735895892675Stnog:matrix.org", 
        {
          "sha256": "WYqp/CKCoVHURPOosQAYaKWiQf8FIcR63SNA9zRRxZw"
        }
      ], 
      [
        "$152735895692673mNESD:matrix.org", 
        {
          "sha256": "gM4O3VPYPXIIk/W589DUu/FVY0qarC1/qIWcUr21weo"
        }
      ], 
      [
        "$152735895992676SrVyB:matrix.org", 
        {
          "sha256": "v53QKB592/sT5+vfHODuxp2H8CYzVx6EVnGuSXb3NfQ"
        }
      ]
    ], 
    "hashes": {
      "sha256": "OHJZxQKKUz/GS+GoOixWUJJajvB/MxyQGFQgoayYrjE"
    }, 
    "type": "m.room.member"
  }, 
  "method": "PUT"
}

Arguments passed as a result to nacl.bindings.crypto_sign.crypto_sign_open() function:

  • signed (concatenation of 64-octet signature and signed data), represented as Python string:
'd\xfc\x9c\xae\xf8\x05*\xdeA\xf6u0\x0f,h\x9b\x82\xd2*+\xdd\x80\xbcKi\x93>\x12\x8em\xeb!A\r\x07C\xf3\x04\xfd\x07\xe4\xfb@=5\xb6\xf8SwG\xea\x1b>\xfc\xec\xbb\xeddA^\xf4k\x10\t{"content":{"auth_events":[["$152735895692674zWMqz:matrix.org",{"sha256":"8UObuZNGmyJ08TQ6aDiim0lAP/Xvcz3QJ4+I9cBlOc8"}],["$152735895892675Stnog:matrix.org",{"sha256":"WYqp/CKCoVHURPOosQAYaKWiQf8FIcR63SNA9zRRxZw"}],["$152735895692673mNESD:matrix.org",{"sha256":"gM4O3VPYPXIIk/W589DUu/FVY0qarC1/qIWcUr21weo"}],["$152735895992676SrVyB:matrix.org",{"sha256":"v53QKB592/sT5+vfHODuxp2H8CYzVx6EVnGuSXb3NfQ"}]],"content":{"avatar_url":"mxc://infoserver.lv/XbHFzOXJypHstVGnsFlRcSTC","displayname":"Oleg Girko","is_direct":true,"membership":"invite"},"depth":7,"event_id":"$152735895992679nRnho:matrix.org","hashes":{"sha256":"OHJZxQKKUz/GS+GoOixWUJJajvB/MxyQGFQgoayYrjE"},"membership":"invite","origin":"matrix.org","origin_server_ts":1527358959995,"prev_events":[["$152735895992678Hezxs:matrix.org",{"sha256":"27kUzkmXpFGXQub7vTwvdcP1U9PTjNzBZSoWBeYJpHM"}]],"prev_state":[],"room_id":"!TgLZRSYjbikNgCOWLA:matrix.org","sender":"@iav:matrix.org","signatures":{"matrix.org":{"ed25519:auto":"RbIga6iJjGBfC3A8Za4C6AZJ03ZHhGzXpAbO3VvOIbGOsQV+uDgGCxVZbBx7Cam9rk50nybdzcCgHxNb6XhNCA"}},"state_key":"@ol:infoserver.lv","type":"m.room.member","unsigned":{"age":549,"invite_room_state":[{"content":{"join_rule":"invite"},"sender":"@iav:matrix.org","state_key":"","type":"m.room.join_rules"},{"content":{"avatar_url":"mxc://matrix.org/kVrxVLSbutexWwcDZSXzwgZK","displayname":"iav","membership":"join"},"sender":"@iav:matrix.org","state_key":"@iav:matrix.org","type":"m.room.member"}]}},"destination":"infoserver.lv","method":"PUT","origin":"matrix.org","uri":"/_matrix/federation/v1/invite/!TgLZRSYjbikNgCOWLA:matrix.org/$152735895992679nRnho:matrix.org"}`

pk (public key), represented as Python string:

'6\x88\xbaZ\xa7\x03\x8fD&?\x10\x8dB\xa8\x1e\xcf\x04\xe5\x04\xaa\xdf\xa9\xe8X\xd6\xed\x85\xc9c\xfd\xb9\x8c'

Result: BadSignatureError exception raised.

@OlegGirko
Copy link
Contributor

Another interesting finding.
I've added additional logging to my Apache HTTPD and found that Authorization: header that Apache receives is exactly the same as Synapse receives.
This rules out possibility of mod_proxy or mod_cache messing with Authorization: header.

@OlegGirko
Copy link
Contributor

Another update.
I've installed Synapse 0.26.0 from Fedora repo (not from my OBS that has 0.30.0).
Invitations from 0.26.0 work perfectly.

@OlegGirko
Copy link
Contributor

After I've upgraded another server to 0.30.0 (from my OBS), invitations stopped working.

@ara4n
Copy link
Member

ara4n commented May 27, 2018

There's also another report of signature check failures at https://riot.im/develop/#/room/#matrix-dev:matrix.org/$15273484311ZxXNG:theta.eu.org

@OlegGirko
Copy link
Contributor

By adding debug print statements to another server, I've found what causes discrepancy between sent and received data. The difference is in URL. Another server (federation client) sends the following URL:

/_matrix/federation/v1/invite/%21TgLZRSYjbikNgCOWLA%3Amatrix.org/%24152735895992679nRnho%3Amatrix.org

But the server itself receives the following URL:

/_matrix/federation/v1/invite/!TgLZRSYjbikNgCOWLA:matrix.org/$152735895992679nRnho:matrix.org

Note that URL being sent has !, $ and : is urlquoted, whereas received URL has them not urlquoted.
Federation client signs JSON with urlquoted URL, but federation server somehow receives non-urlquoted URL and tries to verify JSON with it. If URL contains characters that were escaped originally, verification predictably fails.

Quoting URL for sending (and signing JSON with it) was introduced in dab87b8 of #3082 and this change was included in v0.27.3.

It's interesting to note that Apache HTTPD logs show quoted URL. So, it's still possible that it's mod_proxy that unquotes URLs.

Investigating further...

@OlegGirko
Copy link
Contributor

Great success!

Yes, it was mod_proxy who was canonicalising URL before passing it to the backend server.
But there is a solution: nocanon option for ProxyPass directive.
Now my reverse proxy configuration looks like this:

ProxyPass /_matrix http://127.0.0.1:8008/_matrix timeout=600 nocanon
ProxyPassReverse /_matrix http://127.0.0.1:8008/_matrix

(please ignore timeout option, it's irrelevant for this discussion, I've added it when my server was overloaded).

Problem solved!

A note should be added to "Using a reverse proxy with Synapse" section of Synapse README that revese proxy should be configured without URL canonicalisation.

@remjey
Copy link
Contributor

remjey commented May 27, 2018

Thanks a lot @OlegGirko

I am using nginx and I had the same problem. Here is my previous configuration:

location /_matrix/ {
  proxy_pass http://localhost:8008/_matrix/
  [...]
}

I changed the proxy_pass line to proxy_pass http://localhost:8008 (I removed the whole path).

The nginx proxy_pass documentation states that without a path after the server in the proxy_pass line, the URL is not normalized if it is an original request.

@fadenb
Copy link
Author

fadenb commented May 27, 2018

@remjey your mentioned fix is working fine for me. 👍

I believe this to be a bug, my understanding of the RFCs is that at least the : may or may not be encoded (not a reserved character for the path part of the URL). So one should expect it in both forms?

@richvdh richvdh changed the title "Invalid signature for server ..." resulting in inability to accept invites Nginx reverse proxy causes "Invalid signature for server ..." resulting in inability to accept invites Jun 18, 2018
@richvdh richvdh changed the title Nginx reverse proxy causes "Invalid signature for server ..." resulting in inability to accept invites Reverse proxy causes "Invalid signature for server ..." resulting in inability to accept invites Jun 18, 2018
@richvdh
Copy link
Member

richvdh commented Jun 18, 2018

Sigh. The right solution is probably to closely specify how URL should be encoded, and ensure that is done at both ends before signing/verifying.

For now, we should probably just add a warning to the list of things to be careful of when reverse-proxying federation: https://github.com/matrix-org/synapse/blob/master/README.rst#reverse-proxying-the-federation-port.

@slipeer
Copy link
Contributor

slipeer commented Jul 26, 2018

May be inserting something like:

    json_object['uri'] = '/'.join(
        tuple(
            urllib.quote(urllib.unquote(arg), safe='') for arg in json_object.get('uri').split('/')
        )
    )

before line https://github.com/matrix-org/synapse/blob/develop/synapse/crypto/keyring.py#L784 completely solve the problem?

@slipeer
Copy link
Contributor

slipeer commented Aug 1, 2018

Small fix - do not touch query parameters:

parts = urlparse.urlsplit(json_object.get('uri'))
path = '/'.join(
    tuple(
        urllib.quote(urllib.unquote(arg), safe='') for arg in parts[2].split('/')
    )
)
json_object['uri'] = urlparse.urlunparse(('', '', path, '', parts[3],  ''))

@richvdh
Copy link
Member

richvdh commented Feb 8, 2019

This is a thing that is still a problem, an we really need to take the time to figure out properly.

@maxidorius
Copy link
Contributor

maxidorius commented Feb 8, 2019

Also got hit by this in v0.99 with apache2 acting as a reverse-proxy on the federation port.

Stock apache2 config from debian stretch and this was my virtualhost:

<VirtualHost *:8448>
	ServerName matrix.example.org
	ServerAlias example.org

	SSLEngine on
	SSLCertificateFile /etc/letsencrypt/live/matrix.example.org/fullchain.pem
	SSLCertificateKeyFile /etc/letsencrypt/live/matrix.example.org/privkey.pem
	Header always set Strict-Transport-Security "max-age=31536000; preload"

	DocumentRoot /var/www/matrix.example.org/_8448/public
	ProxyPass /_matrix/ http://synapse:8448/_matrix/
</VirtualHost>

synapse was configured with disabled TLS on the federation port, but no certificate config was changed.

Switching to nginx worked.

@ptman
Copy link
Contributor

ptman commented Feb 9, 2019

@maxidorius you didn't by any chance check if nocanon would have worked with apache?

@OlegGirko
Copy link
Contributor

I've already checked (see my comments from May 27 2018 above) and I can ensure that it won't work without nocanon.

@maxidorius
Copy link
Contributor

@ptman I did not check, no.

@OlegGirko
Copy link
Contributor

@ptman, @maxidorius:
Guys, what are you talking about? Did you read my comments above?
You must use nocanon with ProxyPass directive. Otherwise your homeserver will not work correctly. If you have no nocanon you will definitely have the problem described in this issue.

@maxidorius
Copy link
Contributor

@OlegGirko yes your comments are for port 8008, which is in the recommended setup for client API only and reverse proxy was NOT recommended for federation port (8448) until v0.99 of synapse.

v0.99 now accepts regular certificates. My comment was specifically targeted at v0.99 which supports reverse proxy as per synapse devs themselves. My comments was therefore that stock Apache2, on federation port (8448) does not work out of the box.

Whichever way that ends up being translated in terms of documentation is up to them. I am merely reporting the issue(s) I'm running into and a regular user expectation that if it works on C2S, it should work on S2S easily. That it doesn't is either a lack of clear documentation about it, or possibly a bug on how the path is dealt with when checking signatures. The spec doc doesn't talk about encoding in the path, so I guess that can lead to signatures errors anyway.

@OlegGirko
Copy link
Contributor

@maxidorius:
No, my comments are not about port 8008 and not about client API. They are about using federation behind reverse proxy, no matter what port number or certificate you use. Using normal certificates before 0.99 was not recommended, but it was not forbidden as well, and it's completely irrelevant to this issue. You'll have exactly the same problem with self-signed cert if you use reverse proxy and forget to use nocanon option with ProxyPass directive.

My comments was therefore that stock Apache2, on federation port (8448) does not work out of the box.

And it should not. If you want to use reverse proxy, you have to configure it first. And using ProxyPass without nocanon is incorrect for federation.

There is no expectation that if ProxyPass without nocanon works for client connections then it should work for federation. You should have already known that client connections and federation are different enough, and you can not construe that they became the same just from the fact that using normal cert changed its status from "not recommended, but supported" to "required". This issue is not about cert management at all, it's about rewriting headers by reverse proxy.

There is no need to report this issue again. The case is closed long ago, solution is well-known. I think, the only reason why this issue is still open is that there is no clear long-term resolution: whether it's enough to leave a requirement to use nocanon for federation in documentation, or it's better to change Synapse to be more tolerant to header rewriting by proxies (if possible at all).

@richvdh
Copy link
Member

richvdh commented Feb 10, 2019

Please guys, be nice to each other and take the time to understand what others are saying. There's no need to get angry about it. I think the situation is fairly clear:

  • As @OlegGirko has already reported, using Apache as a reverse-proxy for the federation port without nocanon will make federation unreliable. Thanks to him for doing the original investigation here.

  • Sadly we (I) had forgotten to do anything about it, and as @maxidorius says we are now making the use of a reverse-proxy on the federation port a supported configuration. Thanks to him for reminding us that it's now a bigger problem.

To solve the problem, we either need to make it very clear in our documentation that you need to use nocanon; or, (preferably, imho), we need to update Synapse's behaviour so that it doesn't matter whether you use nocanon or not. Either way, there is work to be done in the Synapse project.

@maxidorius
Copy link
Contributor

@richvdh Thank you for summarizing my feedback nicely.

@OlegGirko
Copy link
Contributor

OlegGirko commented Feb 10, 2019

@richvdh:

As @OlegGirko has already reported, using Apache as a reverse-proxy for the federation port without nocanon will make federation unreliable.

The word "unreliable" doesn't sound right here. It means "sometimes working, sometimes not", but in reality it's deep in "not working at all" territory. Messages still pass through, but invitation requests don't pass at all.

To solve the problem, we either need to make it very clear in our documentation that you need to use nocanon; or, (preferably, imho), we need to update Synapse's behaviour so that it doesn't matter whether you use nocanon or not.

But there is no time for deliberation whether to use first or second approach. First approach should be implemented immediately right now, and requirement to disable URL canonicalisation should be so prominent in documentation that we see no further confusion about it. I think this should also be mentioned in upgrade instructions to prevent this problem appearing in case someone decides to reuse reverse proxy configuration that was used for client-only requests before.

As the long-term solution, I would also prefer if Synapse was converting URLs to its own canonicalised representation for federation before signing and checking for signature correctness. This will not only lift the requirement for disabling URL canonicalisation by reverse proxy, but also prevent possible problems in case there is some non-reverse (probably transparent) proxy between federating homeservers. However, I don't think that it's realistic to expect this solution to be implemented quickly enough to not bother with first (documentation-based) solution.

@richvdh
Copy link
Member

richvdh commented Feb 10, 2019

Having looked at this a little more:

It appears that apache will 404 any request with a %2F in the URL unless nocanon is set. It's very much valid for our parameters (particularly event IDs) to contain slashes, so I don't think we have any choice but to require people to set nocanon.

I haven't dug into the nginx case particularly, but fewer people seem to be getting tripped up by that.

I'll try to fix up the documentation this week.

@OlegGirko
Copy link
Contributor

Isn't it a violation of HTTP protocol to treat for / and %2F in URL different way?

I have a feeling that allowing anything that can have / inside to be a component of a path in URL is very bad idea. This stuff is more suitable for query parameters or request body.

I understand that when federation protocol was originally designed, nobody envisioned usernames like /dev/ponies, and this is a big oversight. This stuff should be either forbidden completely, or moved out of URL anyway.

@richvdh
Copy link
Member

richvdh commented Feb 11, 2019

Actually it turns out that the README has told you to use nocanon since #3783, so I don't think there's much left to do here.

(separately, #4607 is an attempt to clarify the correct configuration for reverse-proxies)

@createcandle
Copy link

createcandle commented Apr 5, 2022

Could this issue be re-opened? It would be nice if this apache configuration fragility could be avoided. I just spend the better part of a day wrestling with this before realizing it wasn't my code or the Nio library, but a completely random server misconfiguration (on a server which I don't control).

Apparently a fix is technically possible? #3611

@richvdh
Copy link
Member

richvdh commented Apr 5, 2022

Making this less fragile is a protocol issue, not a synapse one. It is already tracked at matrix-org/matrix-spec#561.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants