2 * Copyright (c) 2015 Patrick Kelsey
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * This is a server-side implementation of TCP Fast Open (TFO) [RFC7413].
30 * This implementation is currently considered to be experimental and is not
31 * included in kernel builds by default. To include this code, add the
32 * following line to your kernel config:
36 * The generated TFO cookies are the 64-bit output of
37 * SipHash24(<16-byte-key><client-ip>). Multiple concurrent valid keys are
38 * supported so that time-based rolling cookie invalidation policies can be
39 * implemented in the system. The default number of concurrent keys is 2.
40 * This can be adjusted in the kernel config as follows:
42 * options TCP_RFC7413_MAX_KEYS=<num-keys>
45 * The following TFO-specific sysctls are defined:
47 * net.inet.tcp.fastopen.acceptany (RW, default 0)
48 * When non-zero, all client-supplied TFO cookies will be considered to
51 * net.inet.tcp.fastopen.autokey (RW, default 120)
52 * When this and net.inet.tcp.fastopen.enabled are non-zero, a new key
53 * will be automatically generated after this many seconds.
55 * net.inet.tcp.fastopen.enabled (RW, default 0)
56 * When zero, no new TFO connections can be created. On the transition
57 * from enabled to disabled, all installed keys are removed. On the
58 * transition from disabled to enabled, if net.inet.tcp.fastopen.autokey
59 * is non-zero and there are no keys installed, a new key will be
60 * generated immediately. The transition from enabled to disabled does
61 * not affect any TFO connections in progress; it only prevents new ones
64 * net.inet.tcp.fastopen.keylen (RO)
65 * The key length in bytes.
67 * net.inet.tcp.fastopen.maxkeys (RO)
68 * The maximum number of keys supported.
70 * net.inet.tcp.fastopen.numkeys (RO)
71 * The current number of keys installed.
73 * net.inet.tcp.fastopen.setkey (WO)
74 * Install a new key by writing net.inet.tcp.fastopen.keylen bytes to this
78 * In order for TFO connections to be created via a listen socket, that
79 * socket must have the TCP_FASTOPEN socket option set on it. This option
80 * can be set on the socket either before or after the listen() is invoked.
81 * Clearing this option on a listen socket after it has been set has no
82 * effect on existing TFO connections or TFO connections in progress; it
83 * only prevents new TFO connections from being made.
85 * For passively-created sockets, the TCP_FASTOPEN socket option can be
86 * queried to determine whether the connection was established using TFO.
87 * Note that connections that are established via a TFO SYN, but that fall
88 * back to using a non-TFO SYN|ACK will have the TCP_FASTOPEN socket option
91 * Per the RFC, this implementation limits the number of TFO connections
92 * that can be in the SYN_RECEIVED state on a per listen-socket basis.
93 * Whenever this limit is exceeded, requests for new TFO connections are
94 * serviced as non-TFO requests. Without such a limit, given a valid TFO
95 * cookie, an attacker could keep the listen queue in an overflow condition
96 * using a TFO SYN flood. This implementation sets the limit at half the
97 * configured listen backlog.
101 #include <sys/cdefs.h>
102 __FBSDID("$FreeBSD$");
104 #include "opt_inet.h"
106 #include <sys/param.h>
107 #include <sys/kernel.h>
108 #include <sys/limits.h>
109 #include <sys/lock.h>
110 #include <sys/rmlock.h>
111 #include <sys/socket.h>
112 #include <sys/socketvar.h>
113 #include <sys/sysctl.h>
114 #include <sys/systm.h>
116 #include <crypto/siphash/siphash.h>
118 #include <net/vnet.h>
120 #include <netinet/in.h>
121 #include <netinet/in_pcb.h>
122 #include <netinet/tcp_fastopen.h>
123 #include <netinet/tcp_var.h>
126 #define TCP_FASTOPEN_KEY_LEN SIPHASH_KEY_LENGTH
128 #if !defined(TCP_RFC7413_MAX_KEYS) || (TCP_RFC7413_MAX_KEYS < 1)
129 #define TCP_FASTOPEN_MAX_KEYS 2
131 #define TCP_FASTOPEN_MAX_KEYS TCP_RFC7413_MAX_KEYS
134 struct tcp_fastopen_keylist {
136 uint8_t key[TCP_FASTOPEN_MAX_KEYS][TCP_FASTOPEN_KEY_LEN];
139 struct tcp_fastopen_callout {
144 SYSCTL_NODE(_net_inet_tcp, OID_AUTO, fastopen, CTLFLAG_RW, 0, "TCP Fast Open");
146 static VNET_DEFINE(int, tcp_fastopen_acceptany) = 0;
147 #define V_tcp_fastopen_acceptany VNET(tcp_fastopen_acceptany)
148 SYSCTL_INT(_net_inet_tcp_fastopen, OID_AUTO, acceptany,
149 CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(tcp_fastopen_acceptany), 0,
150 "Accept any non-empty cookie");
152 static VNET_DEFINE(unsigned int, tcp_fastopen_autokey) = 120;
153 #define V_tcp_fastopen_autokey VNET(tcp_fastopen_autokey)
154 static int sysctl_net_inet_tcp_fastopen_autokey(SYSCTL_HANDLER_ARGS);
155 SYSCTL_PROC(_net_inet_tcp_fastopen, OID_AUTO, autokey,
156 CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW, NULL, 0,
157 &sysctl_net_inet_tcp_fastopen_autokey, "IU",
158 "Number of seconds between auto-generation of a new key; zero disables");
160 VNET_DEFINE(unsigned int, tcp_fastopen_enabled) = 0;
161 static int sysctl_net_inet_tcp_fastopen_enabled(SYSCTL_HANDLER_ARGS);
162 SYSCTL_PROC(_net_inet_tcp_fastopen, OID_AUTO, enabled,
163 CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW, NULL, 0,
164 &sysctl_net_inet_tcp_fastopen_enabled, "IU",
165 "Enable/disable TCP Fast Open processing");
167 SYSCTL_INT(_net_inet_tcp_fastopen, OID_AUTO, keylen,
168 CTLFLAG_RD, SYSCTL_NULL_INT_PTR, TCP_FASTOPEN_KEY_LEN,
169 "Key length in bytes");
171 SYSCTL_INT(_net_inet_tcp_fastopen, OID_AUTO, maxkeys,
172 CTLFLAG_RD, SYSCTL_NULL_INT_PTR, TCP_FASTOPEN_MAX_KEYS,
173 "Maximum number of keys supported");
175 static VNET_DEFINE(unsigned int, tcp_fastopen_numkeys) = 0;
176 #define V_tcp_fastopen_numkeys VNET(tcp_fastopen_numkeys)
177 SYSCTL_UINT(_net_inet_tcp_fastopen, OID_AUTO, numkeys,
178 CTLFLAG_VNET | CTLFLAG_RD, &VNET_NAME(tcp_fastopen_numkeys), 0,
179 "Number of keys installed");
181 static int sysctl_net_inet_tcp_fastopen_setkey(SYSCTL_HANDLER_ARGS);
182 SYSCTL_PROC(_net_inet_tcp_fastopen, OID_AUTO, setkey,
183 CTLFLAG_VNET | CTLTYPE_OPAQUE | CTLFLAG_WR, NULL, 0,
184 &sysctl_net_inet_tcp_fastopen_setkey, "",
185 "Install a new key");
187 static VNET_DEFINE(struct rmlock, tcp_fastopen_keylock);
188 #define V_tcp_fastopen_keylock VNET(tcp_fastopen_keylock)
190 #define TCP_FASTOPEN_KEYS_RLOCK(t) rm_rlock(&V_tcp_fastopen_keylock, (t))
191 #define TCP_FASTOPEN_KEYS_RUNLOCK(t) rm_runlock(&V_tcp_fastopen_keylock, (t))
192 #define TCP_FASTOPEN_KEYS_WLOCK() rm_wlock(&V_tcp_fastopen_keylock)
193 #define TCP_FASTOPEN_KEYS_WUNLOCK() rm_wunlock(&V_tcp_fastopen_keylock)
195 static VNET_DEFINE(struct tcp_fastopen_keylist, tcp_fastopen_keys);
196 #define V_tcp_fastopen_keys VNET(tcp_fastopen_keys)
198 static VNET_DEFINE(struct tcp_fastopen_callout, tcp_fastopen_autokey_ctx);
199 #define V_tcp_fastopen_autokey_ctx VNET(tcp_fastopen_autokey_ctx)
201 static VNET_DEFINE(uma_zone_t, counter_zone);
202 #define V_counter_zone VNET(counter_zone)
205 tcp_fastopen_init(void)
207 V_counter_zone = uma_zcreate("tfo", sizeof(unsigned int),
208 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
209 rm_init(&V_tcp_fastopen_keylock, "tfo_keylock");
210 callout_init_rm(&V_tcp_fastopen_autokey_ctx.c,
211 &V_tcp_fastopen_keylock, 0);
212 V_tcp_fastopen_autokey_ctx.v = curvnet;
213 V_tcp_fastopen_keys.newest = TCP_FASTOPEN_MAX_KEYS - 1;
217 tcp_fastopen_destroy(void)
219 callout_drain(&V_tcp_fastopen_autokey_ctx.c);
220 rm_destroy(&V_tcp_fastopen_keylock);
221 uma_zdestroy(V_counter_zone);
225 tcp_fastopen_alloc_counter(void)
227 unsigned int *counter;
228 counter = uma_zalloc(V_counter_zone, M_NOWAIT);
235 tcp_fastopen_decrement_counter(unsigned int *counter)
238 uma_zfree(V_counter_zone, counter);
240 atomic_subtract_int(counter, 1);
244 tcp_fastopen_addkey_locked(uint8_t *key)
247 V_tcp_fastopen_keys.newest++;
248 if (V_tcp_fastopen_keys.newest == TCP_FASTOPEN_MAX_KEYS)
249 V_tcp_fastopen_keys.newest = 0;
250 memcpy(V_tcp_fastopen_keys.key[V_tcp_fastopen_keys.newest], key,
251 TCP_FASTOPEN_KEY_LEN);
252 if (V_tcp_fastopen_numkeys < TCP_FASTOPEN_MAX_KEYS)
253 V_tcp_fastopen_numkeys++;
257 tcp_fastopen_autokey_locked(void)
259 uint8_t newkey[TCP_FASTOPEN_KEY_LEN];
261 arc4rand(newkey, TCP_FASTOPEN_KEY_LEN, 0);
262 tcp_fastopen_addkey_locked(newkey);
266 tcp_fastopen_autokey_callout(void *arg)
268 struct tcp_fastopen_callout *ctx = arg;
271 tcp_fastopen_autokey_locked();
272 callout_reset(&ctx->c, V_tcp_fastopen_autokey * hz,
273 tcp_fastopen_autokey_callout, ctx);
279 tcp_fastopen_make_cookie(uint8_t key[SIPHASH_KEY_LENGTH], struct in_conninfo *inc)
284 SipHash24_Init(&ctx);
285 SipHash_SetKey(&ctx, key);
286 switch (inc->inc_flags & INC_ISIPV6) {
289 SipHash_Update(&ctx, &inc->inc_faddr, sizeof(inc->inc_faddr));
294 SipHash_Update(&ctx, &inc->inc6_faddr, sizeof(inc->inc6_faddr));
298 SipHash_Final((u_int8_t *)&siphash, &ctx);
306 * -1 the cookie is invalid and no valid cookie is available
307 * 0 the cookie is invalid and the latest cookie has been returned
308 * 1 the cookie is valid and the latest cookie has been returned
311 tcp_fastopen_check_cookie(struct in_conninfo *inc, uint8_t *cookie,
312 unsigned int len, uint64_t *latest_cookie)
314 struct rm_priotracker tracker;
315 unsigned int i, key_index;
318 if (V_tcp_fastopen_acceptany) {
323 if (len != TCP_FASTOPEN_COOKIE_LEN) {
324 if (V_tcp_fastopen_numkeys > 0) {
326 tcp_fastopen_make_cookie(
327 V_tcp_fastopen_keys.key[V_tcp_fastopen_keys.newest],
335 * Check against each available key, from newest to oldest.
337 TCP_FASTOPEN_KEYS_RLOCK(&tracker);
338 key_index = V_tcp_fastopen_keys.newest;
339 for (i = 0; i < V_tcp_fastopen_numkeys; i++) {
341 tcp_fastopen_make_cookie(V_tcp_fastopen_keys.key[key_index],
344 *latest_cookie = cur_cookie;
345 if (memcmp(cookie, &cur_cookie, TCP_FASTOPEN_COOKIE_LEN) == 0) {
346 TCP_FASTOPEN_KEYS_RUNLOCK(&tracker);
350 key_index = TCP_FASTOPEN_MAX_KEYS - 1;
354 TCP_FASTOPEN_KEYS_RUNLOCK(&tracker);
360 sysctl_net_inet_tcp_fastopen_autokey(SYSCTL_HANDLER_ARGS)
365 new = V_tcp_fastopen_autokey;
366 error = sysctl_handle_int(oidp, &new, 0, req);
367 if (error == 0 && req->newptr) {
368 if (new > (INT_MAX / hz))
371 TCP_FASTOPEN_KEYS_WLOCK();
372 if (V_tcp_fastopen_enabled) {
373 if (V_tcp_fastopen_autokey && !new)
374 callout_stop(&V_tcp_fastopen_autokey_ctx.c);
376 callout_reset(&V_tcp_fastopen_autokey_ctx.c,
377 new * hz, tcp_fastopen_autokey_callout,
378 &V_tcp_fastopen_autokey_ctx);
380 V_tcp_fastopen_autokey = new;
381 TCP_FASTOPEN_KEYS_WUNLOCK();
388 sysctl_net_inet_tcp_fastopen_enabled(SYSCTL_HANDLER_ARGS)
393 new = V_tcp_fastopen_enabled;
394 error = sysctl_handle_int(oidp, &new, 0, req);
395 if (error == 0 && req->newptr) {
396 if (V_tcp_fastopen_enabled && !new) {
397 /* enabled -> disabled */
398 TCP_FASTOPEN_KEYS_WLOCK();
399 V_tcp_fastopen_numkeys = 0;
400 V_tcp_fastopen_keys.newest = TCP_FASTOPEN_MAX_KEYS - 1;
401 if (V_tcp_fastopen_autokey)
402 callout_stop(&V_tcp_fastopen_autokey_ctx.c);
403 V_tcp_fastopen_enabled = 0;
404 TCP_FASTOPEN_KEYS_WUNLOCK();
405 } else if (!V_tcp_fastopen_enabled && new) {
406 /* disabled -> enabled */
407 TCP_FASTOPEN_KEYS_WLOCK();
408 if (V_tcp_fastopen_autokey &&
409 (V_tcp_fastopen_numkeys == 0)) {
410 tcp_fastopen_autokey_locked();
411 callout_reset(&V_tcp_fastopen_autokey_ctx.c,
412 V_tcp_fastopen_autokey * hz,
413 tcp_fastopen_autokey_callout,
414 &V_tcp_fastopen_autokey_ctx);
416 V_tcp_fastopen_enabled = 1;
417 TCP_FASTOPEN_KEYS_WUNLOCK();
424 sysctl_net_inet_tcp_fastopen_setkey(SYSCTL_HANDLER_ARGS)
427 uint8_t newkey[TCP_FASTOPEN_KEY_LEN];
429 if (req->oldptr != NULL || req->oldlen != 0)
431 if (req->newptr == NULL)
433 if (req->newlen != sizeof(newkey))
435 error = SYSCTL_IN(req, newkey, sizeof(newkey));
439 TCP_FASTOPEN_KEYS_WLOCK();
440 tcp_fastopen_addkey_locked(newkey);
441 TCP_FASTOPEN_KEYS_WUNLOCK();