Skip to content

Commit a03980e

Browse files
committed
Experimental support for WireGuard over TCP
1 parent 9a8acb7 commit a03980e

20 files changed

+2581
-949
lines changed

TunSafe.vcxproj

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,10 +185,24 @@
185185
<ClInclude Include="crypto\blake2s\blake2s-sse-impl.h" />
186186
<ClInclude Include="crypto\curve25519\curve25519-donna.h" />
187187
<ClInclude Include="ip_to_peer_map.h" />
188+
<ClInclude Include="network_bsd.h">
189+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
190+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
191+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
192+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
193+
</ClInclude>
194+
<ClInclude Include="network_common.h" />
195+
<ClInclude Include="network_win32_tcp.h" />
188196
<ClInclude Include="service_pipe_win32.h" />
189197
<ClInclude Include="service_win32.h" />
190198
<ClInclude Include="service_win32_api.h" />
191199
<ClInclude Include="service_win32_constants.h" />
200+
<ClInclude Include="tunsafe_bsd.h">
201+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
202+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
203+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
204+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
205+
</ClInclude>
192206
<ClInclude Include="tunsafe_config.h" />
193207
<ClInclude Include="tunsafe_cpu.h" />
194208
<ClInclude Include="crypto\aesgcm\aes.h" />
@@ -215,8 +229,28 @@
215229
<ItemGroup>
216230
<ClCompile Include="benchmark.cpp" />
217231
<ClCompile Include="ip_to_peer_map.cpp" />
232+
<ClCompile Include="network_bsd.cpp">
233+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
234+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
235+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
236+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
237+
</ClCompile>
238+
<ClCompile Include="network_bsd_mt.cpp">
239+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
240+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
241+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
242+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
243+
</ClCompile>
244+
<ClCompile Include="network_common.cpp" />
245+
<ClCompile Include="network_win32_tcp.cpp" />
218246
<ClCompile Include="service_pipe_win32.cpp" />
219247
<ClCompile Include="service_win32.cpp" />
248+
<ClCompile Include="tunsafe_bsd.cpp">
249+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
250+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
251+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
252+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
253+
</ClCompile>
220254
<ClCompile Include="tunsafe_cpu.cpp" />
221255
<ClCompile Include="crypto\aesgcm\aesgcm.cpp" />
222256
<ClCompile Include="crypto\siphash\siphash.cpp" />

TunSafe.vcxproj.filters

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@
2323
<Filter Include="crypto\chacha20poly1305">
2424
<UniqueIdentifier>{1ca37c7b-e91e-4648-9584-7d0c73d8e416}</UniqueIdentifier>
2525
</Filter>
26+
<Filter Include="Source Files\BSD">
27+
<UniqueIdentifier>{4b2f2fd9-780e-45db-8fe1-f03079439723}</UniqueIdentifier>
28+
</Filter>
29+
<Filter Include="crypto\siphash">
30+
<UniqueIdentifier>{0f45e1a0-f33e-4c6e-88ae-eb4639f12041}</UniqueIdentifier>
31+
</Filter>
2632
</ItemGroup>
2733
<ItemGroup>
2834
<ClInclude Include="stdafx.h">
@@ -92,7 +98,6 @@
9298
<ClInclude Include="service_win32_constants.h">
9399
<Filter>Source Files\Win32</Filter>
94100
</ClInclude>
95-
<ClInclude Include="crypto\siphash\siphash.h" />
96101
<ClInclude Include="crypto\blake2s\blake2s.h">
97102
<Filter>crypto\blake2s</Filter>
98103
</ClInclude>
@@ -123,6 +128,21 @@
123128
<ClInclude Include="tunsafe_dnsresolve.h">
124129
<Filter>Source Files</Filter>
125130
</ClInclude>
131+
<ClInclude Include="crypto\siphash\siphash.h">
132+
<Filter>crypto\siphash</Filter>
133+
</ClInclude>
134+
<ClInclude Include="network_bsd.h">
135+
<Filter>Source Files\BSD</Filter>
136+
</ClInclude>
137+
<ClInclude Include="tunsafe_bsd.h">
138+
<Filter>Source Files\BSD</Filter>
139+
</ClInclude>
140+
<ClInclude Include="network_common.h">
141+
<Filter>Source Files</Filter>
142+
</ClInclude>
143+
<ClInclude Include="network_win32_tcp.h">
144+
<Filter>Source Files\Win32</Filter>
145+
</ClInclude>
126146
</ItemGroup>
127147
<ItemGroup>
128148
<ClCompile Include="stdafx.cpp">
@@ -173,9 +193,6 @@
173193
<ClCompile Include="service_pipe_win32.cpp">
174194
<Filter>Source Files\Win32</Filter>
175195
</ClCompile>
176-
<ClCompile Include="crypto\siphash\siphash.cpp">
177-
<Filter>Source Files</Filter>
178-
</ClCompile>
179196
<ClCompile Include="crypto\blake2s\blake2s.cpp">
180197
<Filter>crypto\blake2s</Filter>
181198
</ClCompile>
@@ -188,6 +205,24 @@
188205
<ClCompile Include="tunsafe_ipaddr.cpp">
189206
<Filter>Source Files</Filter>
190207
</ClCompile>
208+
<ClCompile Include="network_bsd.cpp">
209+
<Filter>Source Files\BSD</Filter>
210+
</ClCompile>
211+
<ClCompile Include="network_bsd_mt.cpp">
212+
<Filter>Source Files\BSD</Filter>
213+
</ClCompile>
214+
<ClCompile Include="crypto\siphash\siphash.cpp">
215+
<Filter>crypto\siphash</Filter>
216+
</ClCompile>
217+
<ClCompile Include="tunsafe_bsd.cpp">
218+
<Filter>Source Files\BSD</Filter>
219+
</ClCompile>
220+
<ClCompile Include="network_common.cpp">
221+
<Filter>Source Files</Filter>
222+
</ClCompile>
223+
<ClCompile Include="network_win32_tcp.cpp">
224+
<Filter>Source Files\Win32</Filter>
225+
</ClCompile>
191226
</ItemGroup>
192227
<ItemGroup>
193228
<ResourceCompile Include="TunSafe.rc" />

docs/WireGuard TCP.txt

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
WireGuard over TCP
2+
------------------
3+
4+
We hate running one TCP implementation on top of another TCP implementation.
5+
There's problems with cascading retransmissions and head of line blocking,
6+
and performance is always much worse than a UDP based tunnel.
7+
8+
However, we also recognize that several users need to run WireGuard over TCP.
9+
One reason is that UDP packets are sometimes blocked by the network in
10+
corporate scenarios or in other types of firewalls. Also, in misconfigured
11+
networks outside of the user's control, TCP may be more reliable than UDP.
12+
13+
Additionally, we want TunSafe to be a drop-in replacement for OpenVPN, which
14+
also supports TCP based tunneling. The feature could also be used to run
15+
WireGuard tunnels over ssh tunnels, or through socks/https proxies.
16+
17+
The TunSafe project therefore takes the pragmatic approach of supporting
18+
WireGuard over TCP, while discouraging its use. We absolutely don't want
19+
people to start using TCP by default. It's meant to be used only in the
20+
extreme cases when nothing else is working.
21+
22+
We've added experimental support for TCP in the latest TunSafe master,
23+
which means you can try this out on Windows, OSX, Linux, and FreeBSD.
24+
On the server side, to listen on a TCP port, use ListenPortTCP=1234. (Not
25+
working on Windows yet). On the clients, use Endpoint=tcp://5.5.5.5:1234.
26+
The code is still very experimental and untested, and is not recommended
27+
for general use. Once the code is more well tested, we'll also release
28+
support for connecting to WireGuard over TCP in our Android and iOS clients.
29+
30+
To make the impact as small as possible to our WireGuard protocol handling,
31+
and to minimize the risk of security related issues, the TCP feature has been
32+
designed to be as self-contained as possible. When a packet comes in over
33+
TCP, it's sent over to the WireGuard protocol handler and treated as if it
34+
was a UDP packet, and vice versa. This means TCP support can also be supported
35+
in existing WireGuard deployments by using a separate process that converts
36+
TCP connections into UDP packets sent to the WireGuard Linux kernel module.
37+
38+
Each packet over TCP is prefixed by a 2-byte big endian number, which contains
39+
the length of the packet's payload. The payload is then the actual WireGuard
40+
UDP packet.
41+
42+
TCP has larger overhead than UDP, and we want to support the usual WireGuard
43+
MTU of 1420 without introducing extra packet "fragmenting". So we implemented
44+
an optimization to skip sending the 16-byte WireGuard header for every packet.
45+
TCP is a reliable connection, we know that sequence numbers are always
46+
monotonically increasing, so we can predict the contents of this header.
47+
48+
Here's an example:
49+
A 1420 byte big packet sent over a WireGuard link will have 2 bytes of
50+
TCP payload length, 16 bytes of WireGuard headers, 16 bytes of WireGuard MAC,
51+
20 bytes of TCP headers, and 40 bytes of IPv6 headers.
52+
This is a total of 1420 + 2 + 16 + 16 + 20 + 40 = 1514 bytes, exceeding
53+
the usual 1500 byte Ethernet MTU by 14 bytes. This means that a single full
54+
sized packet over WireGuard will result in 2 TCP packets. With our
55+
optimization, we reduce this to 1498 bytes, so it fits in one TCP packet.
56+
57+
Protocol specification
58+
----------------------
59+
60+
TT LLLLLL LLLLLLLL [Payload LL bytes]
61+
| |
62+
| \-- Payload length, high byte first.
63+
\----- Packet type
64+
65+
The packet types (TT) currently defined are:
66+
TT = 00 = Normal The payload is a normal unmodified WireGuard packet
67+
including the regular WireGuard header.
68+
01 = Reserved
69+
10 = Data A WireGuard data packet (type 04) without the 16 byte
70+
header. The predicted header is prefixed to the payload.
71+
11 = Control A TCP control packet. Currently this is used only to setup
72+
the header prediction. See below.
73+
74+
There's only one defined Control packet, type 00 (SetKeyAndCounter):
75+
76+
0 1 2 3
77+
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
78+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
79+
|1 1| Length is 13 (14 bits) | 00 (8 bits) |
80+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
81+
| Key ID (32 bits) |
82+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
83+
| Counter (64 bits) ...
84+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
85+
86+
This sets up the Key ID and Counter used for the Data packets. Then Counter
87+
is incremented by 1 for every such packet.
88+
89+
For every Data packet, the predicted Key ID and Counter is expanded to a
90+
regular WireGuard data (type 04) header, which is prefixed to the payload:
91+
92+
0 1 2 3
93+
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
94+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
95+
| 04 (8 bits) | Reserved (24 bits) |
96+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
97+
| Key ID (32 bits) |
98+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
99+
| Counter (64 bits) ...
100+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
101+
| Data Payload (LL * 8 bits) ...
102+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
103+
104+
This happens independently in each of the two TCP directions.

netapi.h

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,22 +59,30 @@ struct Packet : QueuedItem {
5959
uint8 userdata;
6060
uint8 protocol; // which protocol is this packet for/from
6161
IpAddr addr; // Optionally set to target/source of the packet
62-
63-
byte data_pre[4];
64-
byte data_buf[0];
62+
6563
enum {
66-
// there's always this much data before data_ptr
64+
// there's always this much data before data_buf, to allow for header expansion
65+
// in front.
6766
HEADROOM_BEFORE = 64,
6867
};
68+
69+
byte data_pre[HEADROOM_BEFORE];
70+
byte data_buf[0];
71+
72+
void Reset() {
73+
data = data_buf;
74+
size = 0;
75+
}
6976
};
7077

7178
enum {
7279
kPacketAllocSize = 2048 - 16,
73-
kPacketCapacity = kPacketAllocSize - sizeof(Packet) - Packet::HEADROOM_BEFORE,
80+
kPacketCapacity = kPacketAllocSize - sizeof(Packet),
7481
};
7582

7683
void FreePacket(Packet *packet);
7784
void FreePackets(Packet *packet, Packet **end, int count);
85+
void FreePacketList(Packet *packet);
7886
Packet *AllocPacket();
7987
void FreeAllPackets();
8088

@@ -123,7 +131,7 @@ class TunInterface {
123131

124132
class UdpInterface {
125133
public:
126-
virtual bool Configure(int listen_port) = 0;
134+
virtual bool Configure(int listen_port_udp, int listen_port_tcp) = 0;
127135
virtual void WriteUdpPacket(Packet *packet) = 0;
128136
};
129137

0 commit comments

Comments
 (0)