2020-06-22 04:15:24 +00:00
|
|
|
|
.\" Man page generated from reStructuredText.
|
|
|
|
|
.
|
|
|
|
|
.
|
|
|
|
|
.nr rst2man-indent-level 0
|
|
|
|
|
.
|
|
|
|
|
.de1 rstReportMargin
|
|
|
|
|
\\$1 \\n[an-margin]
|
|
|
|
|
level \\n[rst2man-indent-level]
|
|
|
|
|
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|
|
|
|
-
|
|
|
|
|
\\n[rst2man-indent0]
|
|
|
|
|
\\n[rst2man-indent1]
|
|
|
|
|
\\n[rst2man-indent2]
|
|
|
|
|
..
|
|
|
|
|
.de1 INDENT
|
|
|
|
|
.\" .rstReportMargin pre:
|
|
|
|
|
. RS \\$1
|
|
|
|
|
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
|
|
|
|
|
. nr rst2man-indent-level +1
|
|
|
|
|
.\" .rstReportMargin post:
|
|
|
|
|
..
|
|
|
|
|
.de UNINDENT
|
|
|
|
|
. RE
|
|
|
|
|
.\" indent \\n[an-margin]
|
|
|
|
|
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|
|
|
|
.nr rst2man-indent-level -1
|
|
|
|
|
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|
|
|
|
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
|
|
|
|
..
|
2022-05-02 04:07:12 +00:00
|
|
|
|
.TH "SYNCTHING-RELAY" "7" "May 01, 2022" "v1.19.2" "Syncthing"
|
2021-04-28 05:45:43 +00:00
|
|
|
|
.SH NAME
|
|
|
|
|
syncthing-relay \- Relay Protocol v1
|
2020-06-22 04:15:24 +00:00
|
|
|
|
.SH WHAT IS A RELAY?
|
|
|
|
|
.sp
|
|
|
|
|
Relay is a service which relays data between two \fIdevices\fP which are not able to
|
|
|
|
|
connect to each other directly otherwise. This is usually due to both devices
|
|
|
|
|
being behind a NAT and neither side being able to open a port which would
|
|
|
|
|
be directly accessible from the internet.
|
|
|
|
|
.sp
|
|
|
|
|
A relay was designed to relay BEP protocol, hence the reliance on device ID’s
|
|
|
|
|
in the protocol spec, but at the same time it is general enough that could be
|
|
|
|
|
reused by other protocols or applications, as the data transferred between two
|
|
|
|
|
devices which use a relay is completely obscure and does not affect the
|
|
|
|
|
relaying.
|
|
|
|
|
.SH OPERATION MODES
|
|
|
|
|
.sp
|
|
|
|
|
Relay listens on a single TCP socket, but has two different connection modes,
|
|
|
|
|
where a connection mode is a predefined set of messages which the relay and
|
|
|
|
|
the device are expecting to exchange.
|
|
|
|
|
.sp
|
|
|
|
|
The first mode is the \fIprotocol\fP mode which allows a client to interact
|
|
|
|
|
with the relay, for example join the relay, or request to connect to a device,
|
|
|
|
|
given it is available on the relay. Similarly to BEP, protocol mode requires
|
|
|
|
|
the device to connect via TLS using a strong suite of ciphers (same as BEP),
|
|
|
|
|
which allows the relay to verify and derive the identity (Device ID) of the
|
|
|
|
|
device.
|
|
|
|
|
.sp
|
|
|
|
|
The second mode is the \fIsession\fP mode which after a few initial messages
|
|
|
|
|
connects two devices directly to each other via the relay, and is a plain\-text
|
|
|
|
|
protocol, which for every byte written by one device, sends the same set of
|
|
|
|
|
bytes to the other device and vica versa.
|
|
|
|
|
.SH IDENTIFYING THE CONNECTION MODE
|
|
|
|
|
.sp
|
|
|
|
|
Because both connection modes operate over the same single socket, a method
|
|
|
|
|
of detecting the connection mode is required.
|
|
|
|
|
.sp
|
|
|
|
|
When a new client connects to the relay, the relay checks the first byte
|
|
|
|
|
that the client has sent, and if that matches 0x16, that implies to us that
|
|
|
|
|
the connection is a protocol mode connection, due to 0x16 being the first byte
|
|
|
|
|
in the TLS handshake, and only protocol mode connections use TLS.
|
|
|
|
|
.sp
|
|
|
|
|
If the first byte is not 0x16, then we assume that the connection is a session
|
|
|
|
|
mode connection.
|
|
|
|
|
.SH PROTOCOL MODE
|
|
|
|
|
.sp
|
|
|
|
|
Protocol mode uses TLS and protocol name defined by the TLS header should be
|
|
|
|
|
\fIbep\-relay\fP\&.
|
|
|
|
|
.sp
|
|
|
|
|
Protocol mode has two submodes:
|
|
|
|
|
1. Permanent protocol submode \- Joining the relay, and waiting for messages from
|
|
|
|
|
the relay asking to connect to some device which is interested in having a
|
|
|
|
|
session with you.
|
|
|
|
|
2. Temporary protocol submode \- Only used to request a session with a device
|
|
|
|
|
which is connected to the relay using the permanent protocol submode.
|
|
|
|
|
.SS Permanent protocol submode
|
|
|
|
|
.sp
|
|
|
|
|
A permanent protocol submode begins with the client sending a JoinRelayRequest
|
|
|
|
|
message, which the relay responds to with either a ResponseSuccess or
|
|
|
|
|
ResponseAlreadyConnected message if a client with the same device ID already
|
|
|
|
|
exists.
|
|
|
|
|
.sp
|
|
|
|
|
After the client has joined, no more messages are exchanged apart from
|
|
|
|
|
Ping/Pong messages for general connection keep alive checking.
|
|
|
|
|
.sp
|
|
|
|
|
From this point onwards, the client stand\-by’s and waits for SessionInvitation
|
|
|
|
|
messages from the relay, which implies that some other device is trying to
|
|
|
|
|
connect with you. SessionInvitation message contains the unique session key
|
|
|
|
|
which then can be used to establish a connection in session mode.
|
|
|
|
|
.sp
|
|
|
|
|
If the client fails to send a JoinRelayRequest message within the first ping
|
|
|
|
|
interval, the connection is terminated.
|
|
|
|
|
If the client fails to send a message (even if it’s a ping message) every minute
|
|
|
|
|
(by default), the connection is terminated.
|
|
|
|
|
.SS Temporary protocol submode
|
|
|
|
|
.sp
|
|
|
|
|
A temporary protocol submode begins with ConnectRequest message, to which the
|
|
|
|
|
relay responds with either ResponseNotFound if the device the client it is after
|
|
|
|
|
is not available, or with a SessionInvitation, which contains the unique session
|
|
|
|
|
key which then can be used to establish a connection in session mode.
|
|
|
|
|
.sp
|
|
|
|
|
The connection is terminated immediately after that.
|
|
|
|
|
.SS Example Exchange
|
|
|
|
|
.sp
|
|
|
|
|
Client A \- Permanent protocol submode
|
|
|
|
|
Client B \- Temporary protocol submode
|
|
|
|
|
.TS
|
|
|
|
|
center;
|
|
|
|
|
|l|l|l|l|.
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
#
|
|
|
|
|
T} T{
|
|
|
|
|
Client (A)
|
|
|
|
|
T} T{
|
|
|
|
|
Relay
|
|
|
|
|
T} T{
|
|
|
|
|
Client (B)
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
1
|
|
|
|
|
T} T{
|
|
|
|
|
JoinRelayRequest\->
|
|
|
|
|
T} T{
|
|
|
|
|
T} T{
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
2
|
|
|
|
|
T} T{
|
|
|
|
|
T} T{
|
|
|
|
|
<\-ResponseSuccess
|
|
|
|
|
T} T{
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
3
|
|
|
|
|
T} T{
|
|
|
|
|
Ping\->
|
|
|
|
|
T} T{
|
|
|
|
|
T} T{
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
4
|
|
|
|
|
T} T{
|
|
|
|
|
T} T{
|
|
|
|
|
<\-Pong
|
|
|
|
|
T} T{
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
5
|
|
|
|
|
T} T{
|
|
|
|
|
T} T{
|
|
|
|
|
T} T{
|
|
|
|
|
<\-ConnectRequest(A)
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
6
|
|
|
|
|
T} T{
|
|
|
|
|
T} T{
|
|
|
|
|
SessionInvitation(A)\->
|
|
|
|
|
T} T{
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
7
|
|
|
|
|
T} T{
|
|
|
|
|
T} T{
|
|
|
|
|
<\-SessionInvitation(B)
|
|
|
|
|
T} T{
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
8
|
|
|
|
|
T} T{
|
|
|
|
|
T} T{
|
|
|
|
|
T} T{
|
|
|
|
|
(Disconnects)
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
9
|
|
|
|
|
T} T{
|
|
|
|
|
Ping\->
|
|
|
|
|
T} T{
|
|
|
|
|
T} T{
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
10
|
|
|
|
|
T} T{
|
|
|
|
|
T} T{
|
|
|
|
|
<\-Pong
|
|
|
|
|
T} T{
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
11
|
|
|
|
|
T} T{
|
|
|
|
|
Ping\->
|
|
|
|
|
T} T{
|
|
|
|
|
T} T{
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
12
|
|
|
|
|
T} T{
|
|
|
|
|
T} T{
|
|
|
|
|
<\-Pong
|
|
|
|
|
T} T{
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
.TE
|
|
|
|
|
.SH SESSION MODE
|
|
|
|
|
.sp
|
|
|
|
|
The first and only message the client sends in the session mode is the
|
|
|
|
|
JoinSessionRequest message which contains the session key identifying which
|
|
|
|
|
session you are trying to join. The relay responds with one of the following
|
|
|
|
|
Response messages:
|
|
|
|
|
.INDENT 0.0
|
|
|
|
|
.IP 1. 3
|
|
|
|
|
ResponseNotFound \- Session key is invalid
|
|
|
|
|
.IP 2. 3
|
|
|
|
|
ResponseAlreadyConnected \- Session is full (both sides already connected)
|
|
|
|
|
.IP 3. 3
|
|
|
|
|
ResponseSuccess \- You have successfully joined the session
|
|
|
|
|
.UNINDENT
|
|
|
|
|
.sp
|
|
|
|
|
After the successful response, all the bytes written and received will be
|
|
|
|
|
relayed between the two devices in the session directly.
|
|
|
|
|
.SS Example Exchange
|
|
|
|
|
.sp
|
|
|
|
|
Client A \- Permanent protocol mode
|
|
|
|
|
Client B \- Temporary protocol mode
|
|
|
|
|
.TS
|
|
|
|
|
center;
|
|
|
|
|
|l|l|l|l|.
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
#
|
|
|
|
|
T} T{
|
|
|
|
|
Client (A)
|
|
|
|
|
T} T{
|
|
|
|
|
Relay
|
|
|
|
|
T} T{
|
|
|
|
|
Client (B)
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
1
|
|
|
|
|
T} T{
|
|
|
|
|
JoinSessionRequest(A)\->
|
|
|
|
|
T} T{
|
|
|
|
|
T} T{
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
2
|
|
|
|
|
T} T{
|
|
|
|
|
T} T{
|
|
|
|
|
<\-ResponseSuccess
|
|
|
|
|
T} T{
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
3
|
|
|
|
|
T} T{
|
|
|
|
|
Data\->
|
|
|
|
|
T} T{
|
|
|
|
|
(Buffers data)
|
|
|
|
|
T} T{
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
4
|
|
|
|
|
T} T{
|
|
|
|
|
Data\->
|
|
|
|
|
T} T{
|
|
|
|
|
(Buffers data)
|
|
|
|
|
T} T{
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
5
|
|
|
|
|
T} T{
|
|
|
|
|
T} T{
|
|
|
|
|
T} T{
|
|
|
|
|
<\-JoinSessionRequest(B)
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
6
|
|
|
|
|
T} T{
|
|
|
|
|
T} T{
|
|
|
|
|
ResponseSuccess\->
|
|
|
|
|
T} T{
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
7
|
|
|
|
|
T} T{
|
|
|
|
|
T} T{
|
|
|
|
|
Relays data \->
|
|
|
|
|
T} T{
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
8
|
|
|
|
|
T} T{
|
|
|
|
|
T} T{
|
|
|
|
|
Relays data \->
|
|
|
|
|
T} T{
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
9
|
|
|
|
|
T} T{
|
|
|
|
|
T} T{
|
|
|
|
|
<\-Relays data
|
|
|
|
|
T} T{
|
|
|
|
|
<\-Data
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
.TE
|
|
|
|
|
.SH MESSAGES
|
|
|
|
|
.sp
|
|
|
|
|
All messages are preceded by a header message. Header message contains the
|
|
|
|
|
magic value 0x9E79BC40, message type integer, and message length.
|
|
|
|
|
.sp
|
|
|
|
|
\fBWARNING:\fP
|
|
|
|
|
.INDENT 0.0
|
|
|
|
|
.INDENT 3.5
|
|
|
|
|
Some messages have no content, apart from the implied header which allows
|
|
|
|
|
us to identify what type of message it is.
|
|
|
|
|
.UNINDENT
|
|
|
|
|
.UNINDENT
|
|
|
|
|
.SS Header structure
|
|
|
|
|
.INDENT 0.0
|
|
|
|
|
.INDENT 3.5
|
|
|
|
|
.sp
|
|
|
|
|
.nf
|
|
|
|
|
.ft C
|
|
|
|
|
0 1 2 3
|
|
|
|
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
| Magic |
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
| Message Type |
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
| Message Length |
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct Header {
|
|
|
|
|
unsigned int Magic;
|
|
|
|
|
int MessageType;
|
|
|
|
|
int MessageLength;
|
|
|
|
|
}
|
|
|
|
|
.ft P
|
|
|
|
|
.fi
|
|
|
|
|
.UNINDENT
|
|
|
|
|
.UNINDENT
|
|
|
|
|
.SS Ping message (Type = 0)
|
|
|
|
|
.INDENT 0.0
|
|
|
|
|
.INDENT 3.5
|
|
|
|
|
.sp
|
|
|
|
|
.nf
|
|
|
|
|
.ft C
|
|
|
|
|
0 1 2 3
|
|
|
|
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct Ping {
|
|
|
|
|
}
|
|
|
|
|
.ft P
|
|
|
|
|
.fi
|
|
|
|
|
.UNINDENT
|
|
|
|
|
.UNINDENT
|
|
|
|
|
.SS Pong message (Type = 1)
|
|
|
|
|
.INDENT 0.0
|
|
|
|
|
.INDENT 3.5
|
|
|
|
|
.sp
|
|
|
|
|
.nf
|
|
|
|
|
.ft C
|
|
|
|
|
0 1 2 3
|
|
|
|
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct Pong {
|
|
|
|
|
}
|
|
|
|
|
.ft P
|
|
|
|
|
.fi
|
|
|
|
|
.UNINDENT
|
|
|
|
|
.UNINDENT
|
|
|
|
|
.SS JoinRelayRequest message (Type = 2)
|
|
|
|
|
.INDENT 0.0
|
|
|
|
|
.INDENT 3.5
|
|
|
|
|
.sp
|
|
|
|
|
.nf
|
|
|
|
|
.ft C
|
|
|
|
|
0 1 2 3
|
|
|
|
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct JoinRelayRequest {
|
|
|
|
|
}
|
|
|
|
|
.ft P
|
|
|
|
|
.fi
|
|
|
|
|
.UNINDENT
|
|
|
|
|
.UNINDENT
|
|
|
|
|
.SS JoinSessionRequest message (Type = 3)
|
|
|
|
|
.INDENT 0.0
|
|
|
|
|
.INDENT 3.5
|
|
|
|
|
.sp
|
|
|
|
|
.nf
|
|
|
|
|
.ft C
|
|
|
|
|
0 1 2 3
|
|
|
|
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
| Length of Key |
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
/ /
|
|
|
|
|
\e Key (variable length) \e
|
|
|
|
|
/ /
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct JoinSessionRequest {
|
|
|
|
|
opaque Key<32>;
|
|
|
|
|
}
|
|
|
|
|
.ft P
|
|
|
|
|
.fi
|
|
|
|
|
.UNINDENT
|
|
|
|
|
.UNINDENT
|
|
|
|
|
.INDENT 0.0
|
|
|
|
|
.TP
|
|
|
|
|
.B : Key
|
|
|
|
|
This is a unique random session key generated by the relay server. It is
|
|
|
|
|
used to identify which session you are trying to connect to.
|
|
|
|
|
.UNINDENT
|
|
|
|
|
.SS Response message (Type = 4)
|
|
|
|
|
.INDENT 0.0
|
|
|
|
|
.INDENT 3.5
|
|
|
|
|
.sp
|
|
|
|
|
.nf
|
|
|
|
|
.ft C
|
|
|
|
|
0 1 2 3
|
|
|
|
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
| Code |
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
| Length of Message |
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
/ /
|
|
|
|
|
\e Message (variable length) \e
|
|
|
|
|
/ /
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct Response {
|
|
|
|
|
int Code;
|
|
|
|
|
string Message<>;
|
|
|
|
|
}
|
|
|
|
|
.ft P
|
|
|
|
|
.fi
|
|
|
|
|
.UNINDENT
|
|
|
|
|
.UNINDENT
|
|
|
|
|
.INDENT 0.0
|
|
|
|
|
.TP
|
|
|
|
|
.B : Code
|
|
|
|
|
An integer representing the status code.
|
|
|
|
|
.TP
|
|
|
|
|
.B : Message
|
|
|
|
|
Message associated with the code.
|
|
|
|
|
.UNINDENT
|
|
|
|
|
.SS ConnectRequest message (Type = 5)
|
|
|
|
|
.INDENT 0.0
|
|
|
|
|
.INDENT 3.5
|
|
|
|
|
.sp
|
|
|
|
|
.nf
|
|
|
|
|
.ft C
|
|
|
|
|
0 1 2 3
|
|
|
|
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
| Length of ID |
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
/ /
|
|
|
|
|
\e ID (variable length) \e
|
|
|
|
|
/ /
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct ConnectRequest {
|
|
|
|
|
opaque ID<32>;
|
|
|
|
|
}
|
|
|
|
|
.ft P
|
|
|
|
|
.fi
|
|
|
|
|
.UNINDENT
|
|
|
|
|
.UNINDENT
|
|
|
|
|
.INDENT 0.0
|
|
|
|
|
.TP
|
|
|
|
|
.B : ID
|
|
|
|
|
Device ID to which the client would like to connect.
|
|
|
|
|
.UNINDENT
|
|
|
|
|
.SS SessionInvitation message (Type = 6)
|
|
|
|
|
.INDENT 0.0
|
|
|
|
|
.INDENT 3.5
|
|
|
|
|
.sp
|
|
|
|
|
.nf
|
|
|
|
|
.ft C
|
|
|
|
|
0 1 2 3
|
|
|
|
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
| Length of From |
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
/ /
|
|
|
|
|
\e From (variable length) \e
|
|
|
|
|
/ /
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
| Length of Key |
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
/ /
|
|
|
|
|
\e Key (variable length) \e
|
|
|
|
|
/ /
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
| Length of Address |
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
/ /
|
|
|
|
|
\e Address (variable length) \e
|
|
|
|
|
/ /
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
| 0x0000 | Port |
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
| Server Socket (V=0 or 1) |V|
|
|
|
|
|
+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+\-+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct SessionInvitation {
|
|
|
|
|
opaque From<32>;
|
|
|
|
|
opaque Key<32>;
|
|
|
|
|
opaque Address<32>;
|
|
|
|
|
unsigned int Port;
|
|
|
|
|
bool ServerSocket;
|
|
|
|
|
}
|
|
|
|
|
.ft P
|
|
|
|
|
.fi
|
|
|
|
|
.UNINDENT
|
|
|
|
|
.UNINDENT
|
|
|
|
|
.INDENT 0.0
|
|
|
|
|
.TP
|
|
|
|
|
.B : From
|
|
|
|
|
Device ID identifying who you will be connecting with.
|
|
|
|
|
.TP
|
|
|
|
|
.B : Key
|
|
|
|
|
A unique random session key generated by the relay server. It is used to
|
|
|
|
|
identify which session you are trying to connect to.
|
|
|
|
|
.TP
|
|
|
|
|
.B : Address
|
|
|
|
|
An optional IP address on which the relay server is expecting you to
|
|
|
|
|
connect, in order to start a connection in session mode.
|
|
|
|
|
Empty/all zero IP should be replaced with the relay’s public IP address that
|
|
|
|
|
was used when establishing the protocol mode connection.
|
|
|
|
|
.TP
|
|
|
|
|
.B : Port
|
|
|
|
|
The port on which the relay server is expecting you to connect,
|
|
|
|
|
in order to start a connection in session mode.
|
|
|
|
|
.TP
|
|
|
|
|
.B : Server Socket
|
|
|
|
|
Because both sides connecting to the relay use the client side of the socket,
|
|
|
|
|
and some protocols behave differently depending if the connection starts on
|
|
|
|
|
the server side or the client side, this boolean indicates which side of the
|
|
|
|
|
connection this client should assume it’s getting. The value is inverted in
|
|
|
|
|
the invitation which is sent to the other device, so that there is always
|
|
|
|
|
one client socket, and one server socket.
|
|
|
|
|
.UNINDENT
|
|
|
|
|
.SH HOW SYNCTHING USES RELAYS, AND GENERAL SECURITY
|
|
|
|
|
.sp
|
|
|
|
|
In the case of Syncthing and BEP, when two devices connect via relay, they
|
|
|
|
|
start their standard TLS connection encapsulated within the relay’s plain\-text
|
|
|
|
|
session connection, effectively upgrading the plain\-text connection to a TLS
|
|
|
|
|
connection.
|
|
|
|
|
.sp
|
|
|
|
|
Even though the relay could be used for man\-in\-the\-middle attack, using TLS
|
|
|
|
|
at the application/BEP level ensures that all the traffic is safely encrypted,
|
|
|
|
|
and is completely meaningless to the relay. Furthermore, the secure suite of
|
|
|
|
|
ciphers used by BEP provides forward secrecy, meaning that even if the relay
|
|
|
|
|
did capture all the traffic, and even if the attacker did get their hands on the
|
|
|
|
|
device keys, they would still not be able to recover/decrypt any traffic which
|
|
|
|
|
was transported via the relay.
|
|
|
|
|
.sp
|
|
|
|
|
After establishing a relay session, Syncthing looks at the SessionInvitation
|
|
|
|
|
message, and depending which side it has received, wraps the raw socket in
|
|
|
|
|
either a TLS client socket or a TLS server socket depending on the ServerSocket
|
|
|
|
|
boolean value in the SessionInvitation, and starts the TLS handshake.
|
|
|
|
|
.sp
|
|
|
|
|
From that point onwards it functions exactly the same way as if Syncthing was
|
|
|
|
|
establishing a direct connection with the other device over the internet,
|
|
|
|
|
performing device ID validation, and full TLS encryption, and provides the same
|
|
|
|
|
security properties as it would provide when connecting over the internet.
|
|
|
|
|
.SH EXAMPLES OF STRONG CIPHER SUITES
|
|
|
|
|
.TS
|
|
|
|
|
center;
|
|
|
|
|
|l|l|l|.
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
ID
|
|
|
|
|
T} T{
|
|
|
|
|
Name
|
|
|
|
|
T} T{
|
|
|
|
|
Description
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
0x009F
|
|
|
|
|
T} T{
|
|
|
|
|
DHE\-RSA\-AES256\-GCM\-SHA384
|
|
|
|
|
T} T{
|
|
|
|
|
TLSv1.2 DH RSA AESGCM(256) AEAD
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
0x006B
|
|
|
|
|
T} T{
|
|
|
|
|
DHE\-RSA\-AES256\-SHA256
|
|
|
|
|
T} T{
|
|
|
|
|
TLSv1.2 DH RSA AES(256) SHA256
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
0xC030
|
|
|
|
|
T} T{
|
|
|
|
|
ECDHE\-RSA\-AES256\-GCM\-SHA384
|
|
|
|
|
T} T{
|
|
|
|
|
TLSv1.2 ECDH RSA AESGCM(256) AEAD
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
0xC028
|
|
|
|
|
T} T{
|
|
|
|
|
ECDHE\-RSA\-AES256\-SHA384
|
|
|
|
|
T} T{
|
|
|
|
|
TLSv1.2 ECDH RSA AES(256) SHA384
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
0x009E
|
|
|
|
|
T} T{
|
|
|
|
|
DHE\-RSA\-AES128\-GCM\-SHA256
|
|
|
|
|
T} T{
|
|
|
|
|
TLSv1.2 DH RSA AESGCM(128) AEAD
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
0x0067
|
|
|
|
|
T} T{
|
|
|
|
|
DHE\-RSA\-AES128\-SHA256
|
|
|
|
|
T} T{
|
|
|
|
|
TLSv1.2 DH RSA AES(128) SHA256
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
0xC02F
|
|
|
|
|
T} T{
|
|
|
|
|
ECDHE\-RSA\-AES128\-GCM\-SHA256
|
|
|
|
|
T} T{
|
|
|
|
|
TLSv1.2 ECDH RSA AESGCM(128) AEAD
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
T{
|
|
|
|
|
0xC027
|
|
|
|
|
T} T{
|
|
|
|
|
ECDHE\-RSA\-AES128\-SHA256
|
|
|
|
|
T} T{
|
|
|
|
|
TLSv1.2 ECDH RSA AES(128) SHA256
|
|
|
|
|
T}
|
|
|
|
|
_
|
|
|
|
|
.TE
|
|
|
|
|
.SH AUTHOR
|
|
|
|
|
The Syncthing Authors
|
|
|
|
|
.SH COPYRIGHT
|
|
|
|
|
2014-2019, The Syncthing Authors
|
|
|
|
|
.\" Generated by docutils manpage writer.
|
|
|
|
|
.
|