xref: /freebsd/sys/netinet/tcp_fastopen.c (revision b0b1dbdd)
1 /*-
2  * Copyright (c) 2015 Patrick Kelsey
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
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
24  * SUCH DAMAGE.
25  */
26 
27 /*
28  * This is a server-side implementation of TCP Fast Open (TFO) [RFC7413].
29  *
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:
33  *
34  * options TCP_RFC7413
35  *
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:
41  *
42  * options TCP_RFC7413_MAX_KEYS=<num-keys>
43  *
44  *
45  * The following TFO-specific sysctls are defined:
46  *
47  * net.inet.tcp.fastopen.acceptany (RW, default 0)
48  *     When non-zero, all client-supplied TFO cookies will be considered to
49  *     be valid.
50  *
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.
54  *
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
62  *     from being made.
63  *
64  * net.inet.tcp.fastopen.keylen (RO)
65  *     The key length in bytes.
66  *
67  * net.inet.tcp.fastopen.maxkeys (RO)
68  *     The maximum number of keys supported.
69  *
70  * net.inet.tcp.fastopen.numkeys (RO)
71  *     The current number of keys installed.
72  *
73  * net.inet.tcp.fastopen.setkey (WO)
74  *     Install a new key by writing net.inet.tcp.fastopen.keylen bytes to this
75  *     sysctl.
76  *
77  *
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.
84  *
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
89  * set.
90  *
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.
98  *
99  */
100 
101 #include <sys/cdefs.h>
102 __FBSDID("$FreeBSD$");
103 
104 #include "opt_inet.h"
105 
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>
115 
116 #include <crypto/siphash/siphash.h>
117 
118 #include <net/vnet.h>
119 
120 #include <netinet/in.h>
121 #include <netinet/in_pcb.h>
122 #include <netinet/tcp_fastopen.h>
123 #include <netinet/tcp_var.h>
124 
125 
126 #define	TCP_FASTOPEN_KEY_LEN	SIPHASH_KEY_LENGTH
127 
128 #if !defined(TCP_RFC7413_MAX_KEYS) || (TCP_RFC7413_MAX_KEYS < 1)
129 #define	TCP_FASTOPEN_MAX_KEYS	2
130 #else
131 #define	TCP_FASTOPEN_MAX_KEYS	TCP_RFC7413_MAX_KEYS
132 #endif
133 
134 struct tcp_fastopen_keylist {
135 	unsigned int newest;
136 	uint8_t key[TCP_FASTOPEN_MAX_KEYS][TCP_FASTOPEN_KEY_LEN];
137 };
138 
139 struct tcp_fastopen_callout {
140 	struct callout c;
141 	struct vnet *v;
142 };
143 
144 SYSCTL_NODE(_net_inet_tcp, OID_AUTO, fastopen, CTLFLAG_RW, 0, "TCP Fast Open");
145 
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");
151 
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");
159 
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");
166 
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");
170 
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");
174 
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");
180 
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");
186 
187 static VNET_DEFINE(struct rmlock, tcp_fastopen_keylock);
188 #define	V_tcp_fastopen_keylock	VNET(tcp_fastopen_keylock)
189 
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)
194 
195 static VNET_DEFINE(struct tcp_fastopen_keylist, tcp_fastopen_keys);
196 #define V_tcp_fastopen_keys	VNET(tcp_fastopen_keys)
197 
198 static VNET_DEFINE(struct tcp_fastopen_callout, tcp_fastopen_autokey_ctx);
199 #define V_tcp_fastopen_autokey_ctx	VNET(tcp_fastopen_autokey_ctx)
200 
201 static VNET_DEFINE(uma_zone_t, counter_zone);
202 #define	V_counter_zone			VNET(counter_zone)
203 
204 void
205 tcp_fastopen_init(void)
206 {
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;
214 }
215 
216 void
217 tcp_fastopen_destroy(void)
218 {
219 	callout_drain(&V_tcp_fastopen_autokey_ctx.c);
220 	rm_destroy(&V_tcp_fastopen_keylock);
221 	uma_zdestroy(V_counter_zone);
222 }
223 
224 unsigned int *
225 tcp_fastopen_alloc_counter(void)
226 {
227 	unsigned int *counter;
228 	counter = uma_zalloc(V_counter_zone, M_NOWAIT);
229 	if (counter)
230 		*counter = 1;
231 	return (counter);
232 }
233 
234 void
235 tcp_fastopen_decrement_counter(unsigned int *counter)
236 {
237 	if (*counter == 1)
238 		uma_zfree(V_counter_zone, counter);
239 	else
240 		atomic_subtract_int(counter, 1);
241 }
242 
243 static void
244 tcp_fastopen_addkey_locked(uint8_t *key)
245 {
246 
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++;
254 }
255 
256 static void
257 tcp_fastopen_autokey_locked(void)
258 {
259 	uint8_t newkey[TCP_FASTOPEN_KEY_LEN];
260 
261 	arc4rand(newkey, TCP_FASTOPEN_KEY_LEN, 0);
262 	tcp_fastopen_addkey_locked(newkey);
263 }
264 
265 static void
266 tcp_fastopen_autokey_callout(void *arg)
267 {
268 	struct tcp_fastopen_callout *ctx = arg;
269 
270 	CURVNET_SET(ctx->v);
271 	tcp_fastopen_autokey_locked();
272 	callout_reset(&ctx->c, V_tcp_fastopen_autokey * hz,
273 		      tcp_fastopen_autokey_callout, ctx);
274 	CURVNET_RESTORE();
275 }
276 
277 
278 static uint64_t
279 tcp_fastopen_make_cookie(uint8_t key[SIPHASH_KEY_LENGTH], struct in_conninfo *inc)
280 {
281 	SIPHASH_CTX ctx;
282 	uint64_t siphash;
283 
284 	SipHash24_Init(&ctx);
285 	SipHash_SetKey(&ctx, key);
286 	switch (inc->inc_flags & INC_ISIPV6) {
287 #ifdef INET
288 	case 0:
289 		SipHash_Update(&ctx, &inc->inc_faddr, sizeof(inc->inc_faddr));
290 		break;
291 #endif
292 #ifdef INET6
293 	case INC_ISIPV6:
294 		SipHash_Update(&ctx, &inc->inc6_faddr, sizeof(inc->inc6_faddr));
295 		break;
296 #endif
297 	}
298 	SipHash_Final((u_int8_t *)&siphash, &ctx);
299 
300 	return (siphash);
301 }
302 
303 
304 /*
305  * Return values:
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
309  */
310 int
311 tcp_fastopen_check_cookie(struct in_conninfo *inc, uint8_t *cookie,
312     unsigned int len, uint64_t *latest_cookie)
313 {
314 	struct rm_priotracker tracker;
315 	unsigned int i, key_index;
316 	uint64_t cur_cookie;
317 
318 	if (V_tcp_fastopen_acceptany) {
319 		*latest_cookie = 0;
320 		return (1);
321 	}
322 
323 	if (len != TCP_FASTOPEN_COOKIE_LEN) {
324 		if (V_tcp_fastopen_numkeys > 0) {
325 			*latest_cookie =
326 			    tcp_fastopen_make_cookie(
327 				V_tcp_fastopen_keys.key[V_tcp_fastopen_keys.newest],
328 				inc);
329 			return (0);
330 		}
331  		return (-1);
332 	}
333 
334 	/*
335 	 * Check against each available key, from newest to oldest.
336 	 */
337 	TCP_FASTOPEN_KEYS_RLOCK(&tracker);
338 	key_index = V_tcp_fastopen_keys.newest;
339 	for (i = 0; i < V_tcp_fastopen_numkeys; i++) {
340 		cur_cookie =
341 		    tcp_fastopen_make_cookie(V_tcp_fastopen_keys.key[key_index],
342 			inc);
343 		if (i == 0)
344 			*latest_cookie = cur_cookie;
345 		if (memcmp(cookie, &cur_cookie, TCP_FASTOPEN_COOKIE_LEN) == 0) {
346 			TCP_FASTOPEN_KEYS_RUNLOCK(&tracker);
347 			return (1);
348 		}
349 		if (key_index == 0)
350 			key_index = TCP_FASTOPEN_MAX_KEYS - 1;
351 		else
352 			key_index--;
353 	}
354 	TCP_FASTOPEN_KEYS_RUNLOCK(&tracker);
355 
356 	return (0);
357 }
358 
359 static int
360 sysctl_net_inet_tcp_fastopen_autokey(SYSCTL_HANDLER_ARGS)
361 {
362 	int error;
363 	unsigned int new;
364 
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))
369 			return (EINVAL);
370 
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);
375 			else if (new)
376 				callout_reset(&V_tcp_fastopen_autokey_ctx.c,
377 				    new * hz, tcp_fastopen_autokey_callout,
378 				    &V_tcp_fastopen_autokey_ctx);
379 		}
380 		V_tcp_fastopen_autokey = new;
381 		TCP_FASTOPEN_KEYS_WUNLOCK();
382 	}
383 
384 	return (error);
385 }
386 
387 static int
388 sysctl_net_inet_tcp_fastopen_enabled(SYSCTL_HANDLER_ARGS)
389 {
390 	int error;
391 	unsigned int new;
392 
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);
415 			}
416 			V_tcp_fastopen_enabled = 1;
417 			TCP_FASTOPEN_KEYS_WUNLOCK();
418 		}
419 	}
420 	return (error);
421 }
422 
423 static int
424 sysctl_net_inet_tcp_fastopen_setkey(SYSCTL_HANDLER_ARGS)
425 {
426 	int error;
427 	uint8_t newkey[TCP_FASTOPEN_KEY_LEN];
428 
429 	if (req->oldptr != NULL || req->oldlen != 0)
430 		return (EINVAL);
431 	if (req->newptr == NULL)
432 		return (EPERM);
433 	if (req->newlen != sizeof(newkey))
434 		return (EINVAL);
435 	error = SYSCTL_IN(req, newkey, sizeof(newkey));
436 	if (error)
437 		return (error);
438 
439 	TCP_FASTOPEN_KEYS_WLOCK();
440 	tcp_fastopen_addkey_locked(newkey);
441 	TCP_FASTOPEN_KEYS_WUNLOCK();
442 
443 	return (0);
444 }
445