Do we need to trust signal server? #73

Closed
opened 2025-11-20 05:05:49 -05:00 by saavagebueno · 9 comments
Owner

Originally created by @le-chat on GitHub (Oct 24, 2021).

From docs it is not clear, how setup key is used during adding new peer. However, given that:

  • setup key looks like uuid
  • setup key shown in web interface equals to one used in command line on peer

I assume that it is used like a shared secret.

This probably means that malicious signal server can insert a MITM between your peers; and when app.wiretrustee.com is hacked, all networks using it are at risk.

It would be nice if less trust is required to signal server. It seems to be possible with public key cryptography, for example:

  • to setup a new network one obtain private key with wg genkey
  • app.wiretrustee.com identifies the network by its public counterpart
  • when new peer is added, it uses private network key to sign own public key and send it via signal server's pub-sub topic, identified by public network key
  • other peers from the given network check signature and only after verification start to trust new public key
  • they send to new peer their public keys, also signed with private network key, plus info about their endpoints, suggested IP for new peer and so on

For enterprise-grade setups with ACLs, audit et cetera one may use private network key as certificate authority which issues keys for joining the network, keys for server(s) who is responsible for IP assigning, keys for audit servers and so on.

Web UI for management in this case may run on any server in the network, and it is safer because sysadmin knows that he/she runs a binary compiled from official sources.

Authorization at app.wiretrustee.com is not mandatory at all, though may be used to manage some additional services like TURN which is not open for anyone.

Do you consider such a scheme? Or am I wrong about currently used one?

Originally created by @le-chat on GitHub (Oct 24, 2021). From docs it is not clear, how setup key is used during adding new peer. However, given that: * setup key looks like uuid * setup key shown in web interface equals to one used in command line on peer I assume that it is used like a shared secret. This probably means that malicious signal server can insert a MITM between your peers; and when app.wiretrustee.com is hacked, *all* networks using it are at risk. It would be nice if less trust is required to signal server. It seems to be possible with public key cryptography, for example: * to setup a new network one obtain _private_ key with `wg genkey` * app.wiretrustee.com identifies the network by its _public_ counterpart * when new peer is added, it uses _private_ network key to sign own public key and send it via signal server's pub-sub topic, identified by public network key * other peers from the given network check signature and only after verification start to trust new public key * they send to new peer their public keys, also signed with private network key, plus info about their endpoints, suggested IP for new peer and so on For enterprise-grade setups with ACLs, audit et cetera one may use private network key as certificate authority which issues keys for joining the network, keys for server(s) who is responsible for IP assigning, keys for audit servers and so on. Web UI for management in this case may run on any server in the network, and it is safer because sysadmin knows that he/she runs a binary compiled from official sources. Authorization at app.wiretrustee.com is not mandatory at all, though may be used to manage some additional services like TURN which is not open for anyone. Do you consider such a scheme? Or am I wrong about currently used one?
Author
Owner

@braginini commented on GitHub (Oct 24, 2021):

Hi @le-chat

Thank you for creating this ticket and expressing your concerns :)
We will definitely add more docs on the architecture touching the points you've mentioned!

What you proposed is pretty much what we have already.

Signal server.
Signal server is a very simple piece of software. It is used only when peers are already registered and are trying to establish connection between each other.
Peers exchange connection candidates (information on how they can reach each other) through signal, encrypting messages with Wireguard keys (private key never leaves the peer).

Simply put, messages that are going through signal are peer-to-peer encrypted and signal can't read them. It just forwards messages routing them using public keys.

You can trust signal :)
In fact, it is very easy to deploy one, or even use someone else's. It is isolated from the rest of the system.

Setup key
Setup key is used only to associate a peer to an account on Management side (app.wiretrustee.com). It is used only on the first run of a peer (when you run wiretrustee login or wiretrustee up commands).

Communication between any peer and Management API is done via gRPC + TLS.
Additionally, Management API exposes it's public Wireguard key. Peers use this key and their own private key to encrypt messages sent to Management.

P.S.
We will be adding SSO+MFA as an alternative way to authenticate a peer.

In future versions we will not store setup keys - the admin user will be able to download them only once, when generating.

Hope this helps!
Let me know if you have any further questions.

@braginini commented on GitHub (Oct 24, 2021): Hi @le-chat Thank you for creating this ticket and expressing your concerns :) We will definitely add more docs on the architecture touching the points you've mentioned! What you proposed is pretty much what we have already. **Signal server.** Signal server is a very simple piece of software. It is used only when peers are already registered and are trying to establish connection between each other. Peers exchange connection candidates (information on how they can reach each other) through signal, encrypting messages with Wireguard keys (private key never leaves the peer). Simply put, messages that are going through signal are peer-to-peer encrypted and signal can't read them. It just forwards messages routing them using public keys. You can trust signal :) In fact, it is very easy to deploy one, or even use someone else's. It is isolated from the rest of the system. **Setup key** Setup key is used only to associate a peer to an account on Management side (app.wiretrustee.com). It is used only on the first run of a peer (when you run wiretrustee login or wiretrustee up commands). Communication between any peer and Management API is done via gRPC + TLS. Additionally, Management API exposes it's public Wireguard key. Peers use this key and their own private key to encrypt messages sent to Management. P.S. We will be adding SSO+MFA as an alternative way to authenticate a peer. In future versions we will not store setup keys - the admin user will be able to download them only once, when generating. Hope this helps! Let me know if you have any further questions.
Author
Owner

@braginini commented on GitHub (Oct 24, 2021):

@le-chat Check out this PDF for some visuals
Wiretrustee explained.pdf

@braginini commented on GitHub (Oct 24, 2021): @le-chat Check out this PDF for some visuals [Wiretrustee explained.pdf](https://github.com/wiretrustee/wiretrustee/files/7406203/Wiretrustee.explained.pdf)
Author
Owner

@le-chat commented on GitHub (Oct 26, 2021):

Thank you. What I'm worried about seems to be called a management server in your terminology, not a signal.

I talk about the following scenario. Alice and Bob want to connect with the help of management server M (for example, app.wiretrustee.com). They create an account with setup_key and use it.

A->M: please join me with public key A.pub and this setup_key
M->A: ok, please use IP 10.0.0.1
B->M: please join me with public key B.pub and this setup_key
M->B: ok, please use IP 10.0.0.2
M->A: you have a peer! ip=10.0.0.2, public_key=M.pub, endpoint=M.ip:666
M->B: you have a peer! ip=10.0.0.1, public_key=M.pub, endpoint=M.ip:667
M: configures wireguard to listen on ports 666 and 667,
   adds peers A.pub and B.pub,
   enables forwarding
A&B: talk to each other with plain HTTP,
     because they think they use end-to-end encrypted peer-to-peer tunnel
M: decrypts all traffic with M's private key

Am I right this is possible with the current scheme?

@le-chat commented on GitHub (Oct 26, 2021): Thank you. What I'm worried about seems to be called a management server in your terminology, not a signal. I talk about the following scenario. Alice and Bob want to connect with the help of management server M (for example, app.wiretrustee.com). They create an account with `setup_key` and use it. ``` A->M: please join me with public key A.pub and this setup_key M->A: ok, please use IP 10.0.0.1 B->M: please join me with public key B.pub and this setup_key M->B: ok, please use IP 10.0.0.2 M->A: you have a peer! ip=10.0.0.2, public_key=M.pub, endpoint=M.ip:666 M->B: you have a peer! ip=10.0.0.1, public_key=M.pub, endpoint=M.ip:667 M: configures wireguard to listen on ports 666 and 667, adds peers A.pub and B.pub, enables forwarding A&B: talk to each other with plain HTTP, because they think they use end-to-end encrypted peer-to-peer tunnel M: decrypts all traffic with M's private key ``` Am I right this is possible with the current scheme?
Author
Owner

@braginini commented on GitHub (Oct 26, 2021):

hey @le-chat
The flow is quite different from what you have described.
Let me describe it using your actors (A, B, M) and Signal (S)

A: generate public and private Wireguard keys
A->M: please register me on a network with public key A.pub with this setup_key
M->A: your IP is 10.64.0.1
B: generate public and private Wireguard keys
B->M: please register me on a network with public key B.pub with this setup_key
M->B: your IP is 10.64.0.2
M->B: there is a peer A already registered in the network,  you can connect to it now with this public key A.pub (IP 10.64.0.1)
M->A: peer B has joined the network, you can connect to it now with this public key B.pub (IP 10.64.0.2)
A->S->B: I want to connect to peer B
B->S->A: I accept the connection of a peer A
A->S->B: here are my DIRECT connection details (IP:port)
B->S->A: here are my DIRECT connection details (IP:port)
A&B: start pinging each other using direct connection ndetails and then establish a peer-to-peer Wireguard connection between each other not involving M and S.

Please note, that A->S->B and B->S->A with S in the middle means that S just forwards a message.
The message itself is peer-to-peer encrypted and S can't read it.

Direct connection details are obtained via NAT hole punching and there can be many of them (just like with WebRTC)

@braginini commented on GitHub (Oct 26, 2021): hey @le-chat The flow is quite different from what you have described. Let me describe it using your actors (A, B, M) and Signal (S) ``` A: generate public and private Wireguard keys A->M: please register me on a network with public key A.pub with this setup_key M->A: your IP is 10.64.0.1 B: generate public and private Wireguard keys B->M: please register me on a network with public key B.pub with this setup_key M->B: your IP is 10.64.0.2 M->B: there is a peer A already registered in the network, you can connect to it now with this public key A.pub (IP 10.64.0.1) M->A: peer B has joined the network, you can connect to it now with this public key B.pub (IP 10.64.0.2) A->S->B: I want to connect to peer B B->S->A: I accept the connection of a peer A A->S->B: here are my DIRECT connection details (IP:port) B->S->A: here are my DIRECT connection details (IP:port) A&B: start pinging each other using direct connection ndetails and then establish a peer-to-peer Wireguard connection between each other not involving M and S. ``` Please note, that A->S->B and B->S->A with S in the middle means that S just forwards a message. The message itself is peer-to-peer encrypted and S can't read it. Direct connection details are obtained via NAT hole punching and there can be many of them (just like with WebRTC)
Author
Owner

@le-chat commented on GitHub (Oct 26, 2021):

Encryption does not mean authentication; M and S knows public keys of A and B and can encrypt any message for them. Malicious M and S could do so:

  • when M sends peer info to A, B, it tells them its own M.pub instead of B.pub, A.pub
  • the first message A->S and the first message B->S are forwarded
  • the second messages from A and B to S are discarded; instead S encrypts and send here are my DIRECT connection details (M.ip:666) and here are my DIRECT connection details (M.ip:667)

After that A&B connects successfully, may ping each other, but M reads all traffic between them.

@le-chat commented on GitHub (Oct 26, 2021): Encryption does not mean authentication; M and S knows public keys of A and B and can encrypt any message for them. Malicious M and S could do so: * when M sends peer info to A, B, it tells them its own M.pub instead of B.pub, A.pub * the first message A->S and the first message B->S are forwarded * the second messages from A and B to S are discarded; instead S encrypts and send `here are my DIRECT connection details (M.ip:666)` and `here are my DIRECT connection details (M.ip:667)` After that A&B connects successfully, may ping each other, but M reads all traffic between them.
Author
Owner

@le-chat commented on GitHub (Oct 26, 2021):

Though if M sends M.pub to A,B, it even does not need alter S behaviour. A and B will send their I want to connect to peer B, I want to connect to peer A to channel for M.pub, M will decrypt their messages and answer as correct signaling client with its own direct connection details.

@le-chat commented on GitHub (Oct 26, 2021): Though if M sends M.pub to A,B, it even does not need alter S behaviour. A and B will send their `I want to connect to peer B`, `I want to connect to peer A` to channel for M.pub, M will decrypt their messages and answer as correct signaling client with its own direct connection details.
Author
Owner

@braginini commented on GitHub (Oct 26, 2021):

You definitely have a point @le-chat
I overlooked in your message that M returns its own details and key, my bad:

M->A: you have a peer! ip=10.0.0.2, public_key=M.pub, endpoint=M.ip:666
M->B: you have a peer! ip=10.0.0.1, public_key=M.pub, endpoint=M.ip:667

I think what you proposed in the original message is possible to implement.
Even though we ensure the safety of the Management server it is always a good idea to have more layers of protection.

I would like to invite you to our Slack chat to further discuss the solution:
https://join.slack.com/t/wiretrustee/shared_invite/zt-vrahf41g-ik1v7fV8du6t0RwxSrJ96A

@braginini commented on GitHub (Oct 26, 2021): You definitely have a point @le-chat I overlooked in your message that M returns its own details and key, my bad: > M->A: you have a peer! ip=10.0.0.2, public_key=**M.pub**, endpoint=**M.ip:666** > M->B: you have a peer! ip=10.0.0.1, public_key=**M.pub**, endpoint=**M.ip:667** I think what you proposed in the original message is possible to implement. Even though we ensure the safety of the Management server it is always a good idea to have more layers of protection. I would like to invite you to our Slack chat to further discuss the solution: https://join.slack.com/t/wiretrustee/shared_invite/zt-vrahf41g-ik1v7fV8du6t0RwxSrJ96A
Author
Owner

@braginini commented on GitHub (Oct 27, 2021):

@le-chat
We had a chat about your proposal and I think there is a quick way of implementing it. Well, at least a part of it.

Wireguard has a PreSharedKey property and we could just make use of it.

We could add an extra flag to the wiretrustee up command that would specify a preshared key and it won't be sent to Management. E.g.:

wiretrustee up --setup-key [setupKey] --preshared-key [predharedKey]

The presharedKey will be an optional flag (for now) but if specified on any peer, on all other peers it should be set as well in order for Wireguard connection be possible.

@braginini commented on GitHub (Oct 27, 2021): @le-chat We had a chat about your proposal and I think there is a quick way of implementing it. Well, at least a part of it. Wireguard has a PreSharedKey property and we could just make use of it. We could add an extra flag to the wiretrustee up command that would specify a preshared key and it won't be sent to Management. E.g.: `wiretrustee up --setup-key [setupKey] --preshared-key [predharedKey]` The presharedKey will be an optional flag (for now) but if specified on any peer, on all other peers it should be set as well in order for Wireguard connection be possible.
Author
Owner

@le-chat commented on GitHub (Oct 28, 2021):

Nice, this seems to prevent described MITM attack and probably is the simplest solution.

Though personally I would like to see no trust at all to management server and use only anonymous signal server :)

@le-chat commented on GitHub (Oct 28, 2021): Nice, this seems to prevent described MITM attack and probably is the simplest solution. Though personally I would like to see no trust at all to management server and use only anonymous signal server :)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: SVI/netbird#73