1*744bfb21SJohn Baldwin /* SPDX-License-Identifier: ISC 2*744bfb21SJohn Baldwin * 3*744bfb21SJohn Baldwin * Copyright (C) 2015-2021 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. 4*744bfb21SJohn Baldwin * Copyright (C) 2019-2021 Matt Dunwoodie <ncon@noconroy.net> 5*744bfb21SJohn Baldwin */ 6*744bfb21SJohn Baldwin 7*744bfb21SJohn Baldwin #include "opt_inet.h" 8*744bfb21SJohn Baldwin #include "opt_inet6.h" 9*744bfb21SJohn Baldwin 10*744bfb21SJohn Baldwin #include <sys/param.h> 11*744bfb21SJohn Baldwin #include <sys/systm.h> 12*744bfb21SJohn Baldwin #include <sys/kernel.h> 13*744bfb21SJohn Baldwin #include <sys/lock.h> 14*744bfb21SJohn Baldwin #include <sys/mutex.h> 15*744bfb21SJohn Baldwin #include <sys/rwlock.h> 16*744bfb21SJohn Baldwin #include <sys/socket.h> 17*744bfb21SJohn Baldwin #include <crypto/siphash/siphash.h> 18*744bfb21SJohn Baldwin #include <netinet/in.h> 19*744bfb21SJohn Baldwin #include <vm/uma.h> 20*744bfb21SJohn Baldwin 21*744bfb21SJohn Baldwin #include "wg_cookie.h" 22*744bfb21SJohn Baldwin 23*744bfb21SJohn Baldwin #define COOKIE_MAC1_KEY_LABEL "mac1----" 24*744bfb21SJohn Baldwin #define COOKIE_COOKIE_KEY_LABEL "cookie--" 25*744bfb21SJohn Baldwin #define COOKIE_SECRET_MAX_AGE 120 26*744bfb21SJohn Baldwin #define COOKIE_SECRET_LATENCY 5 27*744bfb21SJohn Baldwin 28*744bfb21SJohn Baldwin /* Constants for initiation rate limiting */ 29*744bfb21SJohn Baldwin #define RATELIMIT_SIZE (1 << 13) 30*744bfb21SJohn Baldwin #define RATELIMIT_MASK (RATELIMIT_SIZE - 1) 31*744bfb21SJohn Baldwin #define RATELIMIT_SIZE_MAX (RATELIMIT_SIZE * 8) 32*744bfb21SJohn Baldwin #define INITIATIONS_PER_SECOND 20 33*744bfb21SJohn Baldwin #define INITIATIONS_BURSTABLE 5 34*744bfb21SJohn Baldwin #define INITIATION_COST (SBT_1S / INITIATIONS_PER_SECOND) 35*744bfb21SJohn Baldwin #define TOKEN_MAX (INITIATION_COST * INITIATIONS_BURSTABLE) 36*744bfb21SJohn Baldwin #define ELEMENT_TIMEOUT 1 37*744bfb21SJohn Baldwin #define IPV4_MASK_SIZE 4 /* Use all 4 bytes of IPv4 address */ 38*744bfb21SJohn Baldwin #define IPV6_MASK_SIZE 8 /* Use top 8 bytes (/64) of IPv6 address */ 39*744bfb21SJohn Baldwin 40*744bfb21SJohn Baldwin struct ratelimit_key { 41*744bfb21SJohn Baldwin struct vnet *vnet; 42*744bfb21SJohn Baldwin uint8_t ip[IPV6_MASK_SIZE]; 43*744bfb21SJohn Baldwin }; 44*744bfb21SJohn Baldwin 45*744bfb21SJohn Baldwin struct ratelimit_entry { 46*744bfb21SJohn Baldwin LIST_ENTRY(ratelimit_entry) r_entry; 47*744bfb21SJohn Baldwin struct ratelimit_key r_key; 48*744bfb21SJohn Baldwin sbintime_t r_last_time; /* sbinuptime */ 49*744bfb21SJohn Baldwin uint64_t r_tokens; 50*744bfb21SJohn Baldwin }; 51*744bfb21SJohn Baldwin 52*744bfb21SJohn Baldwin struct ratelimit { 53*744bfb21SJohn Baldwin uint8_t rl_secret[SIPHASH_KEY_LENGTH]; 54*744bfb21SJohn Baldwin struct mtx rl_mtx; 55*744bfb21SJohn Baldwin struct callout rl_gc; 56*744bfb21SJohn Baldwin LIST_HEAD(, ratelimit_entry) rl_table[RATELIMIT_SIZE]; 57*744bfb21SJohn Baldwin size_t rl_table_num; 58*744bfb21SJohn Baldwin }; 59*744bfb21SJohn Baldwin 60*744bfb21SJohn Baldwin static void precompute_key(uint8_t *, 61*744bfb21SJohn Baldwin const uint8_t[COOKIE_INPUT_SIZE], const char *); 62*744bfb21SJohn Baldwin static void macs_mac1(struct cookie_macs *, const void *, size_t, 63*744bfb21SJohn Baldwin const uint8_t[COOKIE_KEY_SIZE]); 64*744bfb21SJohn Baldwin static void macs_mac2(struct cookie_macs *, const void *, size_t, 65*744bfb21SJohn Baldwin const uint8_t[COOKIE_COOKIE_SIZE]); 66*744bfb21SJohn Baldwin static int timer_expired(sbintime_t, uint32_t, uint32_t); 67*744bfb21SJohn Baldwin static void make_cookie(struct cookie_checker *, 68*744bfb21SJohn Baldwin uint8_t[COOKIE_COOKIE_SIZE], struct sockaddr *); 69*744bfb21SJohn Baldwin static void ratelimit_init(struct ratelimit *); 70*744bfb21SJohn Baldwin static void ratelimit_deinit(struct ratelimit *); 71*744bfb21SJohn Baldwin static void ratelimit_gc_callout(void *); 72*744bfb21SJohn Baldwin static void ratelimit_gc_schedule(struct ratelimit *); 73*744bfb21SJohn Baldwin static void ratelimit_gc(struct ratelimit *, bool); 74*744bfb21SJohn Baldwin static int ratelimit_allow(struct ratelimit *, struct sockaddr *, struct vnet *); 75*744bfb21SJohn Baldwin static uint64_t siphash13(const uint8_t [SIPHASH_KEY_LENGTH], const void *, size_t); 76*744bfb21SJohn Baldwin 77*744bfb21SJohn Baldwin static struct ratelimit ratelimit_v4; 78*744bfb21SJohn Baldwin #ifdef INET6 79*744bfb21SJohn Baldwin static struct ratelimit ratelimit_v6; 80*744bfb21SJohn Baldwin #endif 81*744bfb21SJohn Baldwin static uma_zone_t ratelimit_zone; 82*744bfb21SJohn Baldwin 83*744bfb21SJohn Baldwin /* Public Functions */ 84*744bfb21SJohn Baldwin int 85*744bfb21SJohn Baldwin cookie_init(void) 86*744bfb21SJohn Baldwin { 87*744bfb21SJohn Baldwin if ((ratelimit_zone = uma_zcreate("wg ratelimit", 88*744bfb21SJohn Baldwin sizeof(struct ratelimit_entry), NULL, NULL, NULL, NULL, 0, 0)) == NULL) 89*744bfb21SJohn Baldwin return ENOMEM; 90*744bfb21SJohn Baldwin 91*744bfb21SJohn Baldwin ratelimit_init(&ratelimit_v4); 92*744bfb21SJohn Baldwin #ifdef INET6 93*744bfb21SJohn Baldwin ratelimit_init(&ratelimit_v6); 94*744bfb21SJohn Baldwin #endif 95*744bfb21SJohn Baldwin return (0); 96*744bfb21SJohn Baldwin } 97*744bfb21SJohn Baldwin 98*744bfb21SJohn Baldwin void 99*744bfb21SJohn Baldwin cookie_deinit(void) 100*744bfb21SJohn Baldwin { 101*744bfb21SJohn Baldwin ratelimit_deinit(&ratelimit_v4); 102*744bfb21SJohn Baldwin #ifdef INET6 103*744bfb21SJohn Baldwin ratelimit_deinit(&ratelimit_v6); 104*744bfb21SJohn Baldwin #endif 105*744bfb21SJohn Baldwin uma_zdestroy(ratelimit_zone); 106*744bfb21SJohn Baldwin } 107*744bfb21SJohn Baldwin 108*744bfb21SJohn Baldwin void 109*744bfb21SJohn Baldwin cookie_checker_init(struct cookie_checker *cc) 110*744bfb21SJohn Baldwin { 111*744bfb21SJohn Baldwin bzero(cc, sizeof(*cc)); 112*744bfb21SJohn Baldwin 113*744bfb21SJohn Baldwin rw_init(&cc->cc_key_lock, "cookie_checker_key"); 114*744bfb21SJohn Baldwin mtx_init(&cc->cc_secret_mtx, "cookie_checker_secret", NULL, MTX_DEF); 115*744bfb21SJohn Baldwin } 116*744bfb21SJohn Baldwin 117*744bfb21SJohn Baldwin void 118*744bfb21SJohn Baldwin cookie_checker_free(struct cookie_checker *cc) 119*744bfb21SJohn Baldwin { 120*744bfb21SJohn Baldwin rw_destroy(&cc->cc_key_lock); 121*744bfb21SJohn Baldwin mtx_destroy(&cc->cc_secret_mtx); 122*744bfb21SJohn Baldwin explicit_bzero(cc, sizeof(*cc)); 123*744bfb21SJohn Baldwin } 124*744bfb21SJohn Baldwin 125*744bfb21SJohn Baldwin void 126*744bfb21SJohn Baldwin cookie_checker_update(struct cookie_checker *cc, 127*744bfb21SJohn Baldwin const uint8_t key[COOKIE_INPUT_SIZE]) 128*744bfb21SJohn Baldwin { 129*744bfb21SJohn Baldwin rw_wlock(&cc->cc_key_lock); 130*744bfb21SJohn Baldwin if (key) { 131*744bfb21SJohn Baldwin precompute_key(cc->cc_mac1_key, key, COOKIE_MAC1_KEY_LABEL); 132*744bfb21SJohn Baldwin precompute_key(cc->cc_cookie_key, key, COOKIE_COOKIE_KEY_LABEL); 133*744bfb21SJohn Baldwin } else { 134*744bfb21SJohn Baldwin bzero(cc->cc_mac1_key, sizeof(cc->cc_mac1_key)); 135*744bfb21SJohn Baldwin bzero(cc->cc_cookie_key, sizeof(cc->cc_cookie_key)); 136*744bfb21SJohn Baldwin } 137*744bfb21SJohn Baldwin rw_wunlock(&cc->cc_key_lock); 138*744bfb21SJohn Baldwin } 139*744bfb21SJohn Baldwin 140*744bfb21SJohn Baldwin void 141*744bfb21SJohn Baldwin cookie_checker_create_payload(struct cookie_checker *cc, 142*744bfb21SJohn Baldwin struct cookie_macs *macs, uint8_t nonce[COOKIE_NONCE_SIZE], 143*744bfb21SJohn Baldwin uint8_t ecookie[COOKIE_ENCRYPTED_SIZE], struct sockaddr *sa) 144*744bfb21SJohn Baldwin { 145*744bfb21SJohn Baldwin uint8_t cookie[COOKIE_COOKIE_SIZE]; 146*744bfb21SJohn Baldwin 147*744bfb21SJohn Baldwin make_cookie(cc, cookie, sa); 148*744bfb21SJohn Baldwin arc4random_buf(nonce, COOKIE_NONCE_SIZE); 149*744bfb21SJohn Baldwin 150*744bfb21SJohn Baldwin rw_rlock(&cc->cc_key_lock); 151*744bfb21SJohn Baldwin xchacha20poly1305_encrypt(ecookie, cookie, COOKIE_COOKIE_SIZE, 152*744bfb21SJohn Baldwin macs->mac1, COOKIE_MAC_SIZE, nonce, cc->cc_cookie_key); 153*744bfb21SJohn Baldwin rw_runlock(&cc->cc_key_lock); 154*744bfb21SJohn Baldwin 155*744bfb21SJohn Baldwin explicit_bzero(cookie, sizeof(cookie)); 156*744bfb21SJohn Baldwin } 157*744bfb21SJohn Baldwin 158*744bfb21SJohn Baldwin void 159*744bfb21SJohn Baldwin cookie_maker_init(struct cookie_maker *cm, const uint8_t key[COOKIE_INPUT_SIZE]) 160*744bfb21SJohn Baldwin { 161*744bfb21SJohn Baldwin bzero(cm, sizeof(*cm)); 162*744bfb21SJohn Baldwin precompute_key(cm->cm_mac1_key, key, COOKIE_MAC1_KEY_LABEL); 163*744bfb21SJohn Baldwin precompute_key(cm->cm_cookie_key, key, COOKIE_COOKIE_KEY_LABEL); 164*744bfb21SJohn Baldwin rw_init(&cm->cm_lock, "cookie_maker"); 165*744bfb21SJohn Baldwin } 166*744bfb21SJohn Baldwin 167*744bfb21SJohn Baldwin void 168*744bfb21SJohn Baldwin cookie_maker_free(struct cookie_maker *cm) 169*744bfb21SJohn Baldwin { 170*744bfb21SJohn Baldwin rw_destroy(&cm->cm_lock); 171*744bfb21SJohn Baldwin explicit_bzero(cm, sizeof(*cm)); 172*744bfb21SJohn Baldwin } 173*744bfb21SJohn Baldwin 174*744bfb21SJohn Baldwin int 175*744bfb21SJohn Baldwin cookie_maker_consume_payload(struct cookie_maker *cm, 176*744bfb21SJohn Baldwin uint8_t nonce[COOKIE_NONCE_SIZE], uint8_t ecookie[COOKIE_ENCRYPTED_SIZE]) 177*744bfb21SJohn Baldwin { 178*744bfb21SJohn Baldwin uint8_t cookie[COOKIE_COOKIE_SIZE]; 179*744bfb21SJohn Baldwin int ret; 180*744bfb21SJohn Baldwin 181*744bfb21SJohn Baldwin rw_rlock(&cm->cm_lock); 182*744bfb21SJohn Baldwin if (!cm->cm_mac1_sent) { 183*744bfb21SJohn Baldwin ret = ETIMEDOUT; 184*744bfb21SJohn Baldwin goto error; 185*744bfb21SJohn Baldwin } 186*744bfb21SJohn Baldwin 187*744bfb21SJohn Baldwin if (!xchacha20poly1305_decrypt(cookie, ecookie, COOKIE_ENCRYPTED_SIZE, 188*744bfb21SJohn Baldwin cm->cm_mac1_last, COOKIE_MAC_SIZE, nonce, cm->cm_cookie_key)) { 189*744bfb21SJohn Baldwin ret = EINVAL; 190*744bfb21SJohn Baldwin goto error; 191*744bfb21SJohn Baldwin } 192*744bfb21SJohn Baldwin rw_runlock(&cm->cm_lock); 193*744bfb21SJohn Baldwin 194*744bfb21SJohn Baldwin rw_wlock(&cm->cm_lock); 195*744bfb21SJohn Baldwin memcpy(cm->cm_cookie, cookie, COOKIE_COOKIE_SIZE); 196*744bfb21SJohn Baldwin cm->cm_cookie_birthdate = getsbinuptime(); 197*744bfb21SJohn Baldwin cm->cm_cookie_valid = true; 198*744bfb21SJohn Baldwin cm->cm_mac1_sent = false; 199*744bfb21SJohn Baldwin rw_wunlock(&cm->cm_lock); 200*744bfb21SJohn Baldwin 201*744bfb21SJohn Baldwin return 0; 202*744bfb21SJohn Baldwin error: 203*744bfb21SJohn Baldwin rw_runlock(&cm->cm_lock); 204*744bfb21SJohn Baldwin return ret; 205*744bfb21SJohn Baldwin } 206*744bfb21SJohn Baldwin 207*744bfb21SJohn Baldwin void 208*744bfb21SJohn Baldwin cookie_maker_mac(struct cookie_maker *cm, struct cookie_macs *macs, void *buf, 209*744bfb21SJohn Baldwin size_t len) 210*744bfb21SJohn Baldwin { 211*744bfb21SJohn Baldwin rw_wlock(&cm->cm_lock); 212*744bfb21SJohn Baldwin macs_mac1(macs, buf, len, cm->cm_mac1_key); 213*744bfb21SJohn Baldwin memcpy(cm->cm_mac1_last, macs->mac1, COOKIE_MAC_SIZE); 214*744bfb21SJohn Baldwin cm->cm_mac1_sent = true; 215*744bfb21SJohn Baldwin 216*744bfb21SJohn Baldwin if (cm->cm_cookie_valid && 217*744bfb21SJohn Baldwin !timer_expired(cm->cm_cookie_birthdate, 218*744bfb21SJohn Baldwin COOKIE_SECRET_MAX_AGE - COOKIE_SECRET_LATENCY, 0)) { 219*744bfb21SJohn Baldwin macs_mac2(macs, buf, len, cm->cm_cookie); 220*744bfb21SJohn Baldwin } else { 221*744bfb21SJohn Baldwin bzero(macs->mac2, COOKIE_MAC_SIZE); 222*744bfb21SJohn Baldwin cm->cm_cookie_valid = false; 223*744bfb21SJohn Baldwin } 224*744bfb21SJohn Baldwin rw_wunlock(&cm->cm_lock); 225*744bfb21SJohn Baldwin } 226*744bfb21SJohn Baldwin 227*744bfb21SJohn Baldwin int 228*744bfb21SJohn Baldwin cookie_checker_validate_macs(struct cookie_checker *cc, struct cookie_macs *macs, 229*744bfb21SJohn Baldwin void *buf, size_t len, bool check_cookie, struct sockaddr *sa, struct vnet *vnet) 230*744bfb21SJohn Baldwin { 231*744bfb21SJohn Baldwin struct cookie_macs our_macs; 232*744bfb21SJohn Baldwin uint8_t cookie[COOKIE_COOKIE_SIZE]; 233*744bfb21SJohn Baldwin 234*744bfb21SJohn Baldwin /* Validate incoming MACs */ 235*744bfb21SJohn Baldwin rw_rlock(&cc->cc_key_lock); 236*744bfb21SJohn Baldwin macs_mac1(&our_macs, buf, len, cc->cc_mac1_key); 237*744bfb21SJohn Baldwin rw_runlock(&cc->cc_key_lock); 238*744bfb21SJohn Baldwin 239*744bfb21SJohn Baldwin /* If mac1 is invald, we want to drop the packet */ 240*744bfb21SJohn Baldwin if (timingsafe_bcmp(our_macs.mac1, macs->mac1, COOKIE_MAC_SIZE) != 0) 241*744bfb21SJohn Baldwin return EINVAL; 242*744bfb21SJohn Baldwin 243*744bfb21SJohn Baldwin if (check_cookie) { 244*744bfb21SJohn Baldwin make_cookie(cc, cookie, sa); 245*744bfb21SJohn Baldwin macs_mac2(&our_macs, buf, len, cookie); 246*744bfb21SJohn Baldwin 247*744bfb21SJohn Baldwin /* If the mac2 is invalid, we want to send a cookie response */ 248*744bfb21SJohn Baldwin if (timingsafe_bcmp(our_macs.mac2, macs->mac2, COOKIE_MAC_SIZE) != 0) 249*744bfb21SJohn Baldwin return EAGAIN; 250*744bfb21SJohn Baldwin 251*744bfb21SJohn Baldwin /* If the mac2 is valid, we may want rate limit the peer. 252*744bfb21SJohn Baldwin * ratelimit_allow will return either 0 or ECONNREFUSED, 253*744bfb21SJohn Baldwin * implying there is no ratelimiting, or we should ratelimit 254*744bfb21SJohn Baldwin * (refuse) respectively. */ 255*744bfb21SJohn Baldwin if (sa->sa_family == AF_INET) 256*744bfb21SJohn Baldwin return ratelimit_allow(&ratelimit_v4, sa, vnet); 257*744bfb21SJohn Baldwin #ifdef INET6 258*744bfb21SJohn Baldwin else if (sa->sa_family == AF_INET6) 259*744bfb21SJohn Baldwin return ratelimit_allow(&ratelimit_v6, sa, vnet); 260*744bfb21SJohn Baldwin #endif 261*744bfb21SJohn Baldwin else 262*744bfb21SJohn Baldwin return EAFNOSUPPORT; 263*744bfb21SJohn Baldwin } 264*744bfb21SJohn Baldwin 265*744bfb21SJohn Baldwin return 0; 266*744bfb21SJohn Baldwin } 267*744bfb21SJohn Baldwin 268*744bfb21SJohn Baldwin /* Private functions */ 269*744bfb21SJohn Baldwin static void 270*744bfb21SJohn Baldwin precompute_key(uint8_t *key, const uint8_t input[COOKIE_INPUT_SIZE], 271*744bfb21SJohn Baldwin const char *label) 272*744bfb21SJohn Baldwin { 273*744bfb21SJohn Baldwin struct blake2s_state blake; 274*744bfb21SJohn Baldwin blake2s_init(&blake, COOKIE_KEY_SIZE); 275*744bfb21SJohn Baldwin blake2s_update(&blake, label, strlen(label)); 276*744bfb21SJohn Baldwin blake2s_update(&blake, input, COOKIE_INPUT_SIZE); 277*744bfb21SJohn Baldwin blake2s_final(&blake, key); 278*744bfb21SJohn Baldwin } 279*744bfb21SJohn Baldwin 280*744bfb21SJohn Baldwin static void 281*744bfb21SJohn Baldwin macs_mac1(struct cookie_macs *macs, const void *buf, size_t len, 282*744bfb21SJohn Baldwin const uint8_t key[COOKIE_KEY_SIZE]) 283*744bfb21SJohn Baldwin { 284*744bfb21SJohn Baldwin struct blake2s_state state; 285*744bfb21SJohn Baldwin blake2s_init_key(&state, COOKIE_MAC_SIZE, key, COOKIE_KEY_SIZE); 286*744bfb21SJohn Baldwin blake2s_update(&state, buf, len); 287*744bfb21SJohn Baldwin blake2s_final(&state, macs->mac1); 288*744bfb21SJohn Baldwin } 289*744bfb21SJohn Baldwin 290*744bfb21SJohn Baldwin static void 291*744bfb21SJohn Baldwin macs_mac2(struct cookie_macs *macs, const void *buf, size_t len, 292*744bfb21SJohn Baldwin const uint8_t key[COOKIE_COOKIE_SIZE]) 293*744bfb21SJohn Baldwin { 294*744bfb21SJohn Baldwin struct blake2s_state state; 295*744bfb21SJohn Baldwin blake2s_init_key(&state, COOKIE_MAC_SIZE, key, COOKIE_COOKIE_SIZE); 296*744bfb21SJohn Baldwin blake2s_update(&state, buf, len); 297*744bfb21SJohn Baldwin blake2s_update(&state, macs->mac1, COOKIE_MAC_SIZE); 298*744bfb21SJohn Baldwin blake2s_final(&state, macs->mac2); 299*744bfb21SJohn Baldwin } 300*744bfb21SJohn Baldwin 301*744bfb21SJohn Baldwin static __inline int 302*744bfb21SJohn Baldwin timer_expired(sbintime_t timer, uint32_t sec, uint32_t nsec) 303*744bfb21SJohn Baldwin { 304*744bfb21SJohn Baldwin sbintime_t now = getsbinuptime(); 305*744bfb21SJohn Baldwin return (now > (timer + sec * SBT_1S + nstosbt(nsec))) ? ETIMEDOUT : 0; 306*744bfb21SJohn Baldwin } 307*744bfb21SJohn Baldwin 308*744bfb21SJohn Baldwin static void 309*744bfb21SJohn Baldwin make_cookie(struct cookie_checker *cc, uint8_t cookie[COOKIE_COOKIE_SIZE], 310*744bfb21SJohn Baldwin struct sockaddr *sa) 311*744bfb21SJohn Baldwin { 312*744bfb21SJohn Baldwin struct blake2s_state state; 313*744bfb21SJohn Baldwin 314*744bfb21SJohn Baldwin mtx_lock(&cc->cc_secret_mtx); 315*744bfb21SJohn Baldwin if (timer_expired(cc->cc_secret_birthdate, 316*744bfb21SJohn Baldwin COOKIE_SECRET_MAX_AGE, 0)) { 317*744bfb21SJohn Baldwin arc4random_buf(cc->cc_secret, COOKIE_SECRET_SIZE); 318*744bfb21SJohn Baldwin cc->cc_secret_birthdate = getsbinuptime(); 319*744bfb21SJohn Baldwin } 320*744bfb21SJohn Baldwin blake2s_init_key(&state, COOKIE_COOKIE_SIZE, cc->cc_secret, 321*744bfb21SJohn Baldwin COOKIE_SECRET_SIZE); 322*744bfb21SJohn Baldwin mtx_unlock(&cc->cc_secret_mtx); 323*744bfb21SJohn Baldwin 324*744bfb21SJohn Baldwin if (sa->sa_family == AF_INET) { 325*744bfb21SJohn Baldwin blake2s_update(&state, (uint8_t *)&satosin(sa)->sin_addr, 326*744bfb21SJohn Baldwin sizeof(struct in_addr)); 327*744bfb21SJohn Baldwin blake2s_update(&state, (uint8_t *)&satosin(sa)->sin_port, 328*744bfb21SJohn Baldwin sizeof(in_port_t)); 329*744bfb21SJohn Baldwin blake2s_final(&state, cookie); 330*744bfb21SJohn Baldwin #ifdef INET6 331*744bfb21SJohn Baldwin } else if (sa->sa_family == AF_INET6) { 332*744bfb21SJohn Baldwin blake2s_update(&state, (uint8_t *)&satosin6(sa)->sin6_addr, 333*744bfb21SJohn Baldwin sizeof(struct in6_addr)); 334*744bfb21SJohn Baldwin blake2s_update(&state, (uint8_t *)&satosin6(sa)->sin6_port, 335*744bfb21SJohn Baldwin sizeof(in_port_t)); 336*744bfb21SJohn Baldwin blake2s_final(&state, cookie); 337*744bfb21SJohn Baldwin #endif 338*744bfb21SJohn Baldwin } else { 339*744bfb21SJohn Baldwin arc4random_buf(cookie, COOKIE_COOKIE_SIZE); 340*744bfb21SJohn Baldwin } 341*744bfb21SJohn Baldwin } 342*744bfb21SJohn Baldwin 343*744bfb21SJohn Baldwin static void 344*744bfb21SJohn Baldwin ratelimit_init(struct ratelimit *rl) 345*744bfb21SJohn Baldwin { 346*744bfb21SJohn Baldwin size_t i; 347*744bfb21SJohn Baldwin mtx_init(&rl->rl_mtx, "ratelimit_lock", NULL, MTX_DEF); 348*744bfb21SJohn Baldwin callout_init_mtx(&rl->rl_gc, &rl->rl_mtx, 0); 349*744bfb21SJohn Baldwin arc4random_buf(rl->rl_secret, sizeof(rl->rl_secret)); 350*744bfb21SJohn Baldwin for (i = 0; i < RATELIMIT_SIZE; i++) 351*744bfb21SJohn Baldwin LIST_INIT(&rl->rl_table[i]); 352*744bfb21SJohn Baldwin rl->rl_table_num = 0; 353*744bfb21SJohn Baldwin } 354*744bfb21SJohn Baldwin 355*744bfb21SJohn Baldwin static void 356*744bfb21SJohn Baldwin ratelimit_deinit(struct ratelimit *rl) 357*744bfb21SJohn Baldwin { 358*744bfb21SJohn Baldwin mtx_lock(&rl->rl_mtx); 359*744bfb21SJohn Baldwin callout_stop(&rl->rl_gc); 360*744bfb21SJohn Baldwin ratelimit_gc(rl, true); 361*744bfb21SJohn Baldwin mtx_unlock(&rl->rl_mtx); 362*744bfb21SJohn Baldwin mtx_destroy(&rl->rl_mtx); 363*744bfb21SJohn Baldwin } 364*744bfb21SJohn Baldwin 365*744bfb21SJohn Baldwin static void 366*744bfb21SJohn Baldwin ratelimit_gc_callout(void *_rl) 367*744bfb21SJohn Baldwin { 368*744bfb21SJohn Baldwin /* callout will lock rl_mtx for us */ 369*744bfb21SJohn Baldwin ratelimit_gc(_rl, false); 370*744bfb21SJohn Baldwin } 371*744bfb21SJohn Baldwin 372*744bfb21SJohn Baldwin static void 373*744bfb21SJohn Baldwin ratelimit_gc_schedule(struct ratelimit *rl) 374*744bfb21SJohn Baldwin { 375*744bfb21SJohn Baldwin /* Trigger another GC if needed. There is no point calling GC if there 376*744bfb21SJohn Baldwin * are no entries in the table. We also want to ensure that GC occurs 377*744bfb21SJohn Baldwin * on a regular interval, so don't override a currently pending GC. 378*744bfb21SJohn Baldwin * 379*744bfb21SJohn Baldwin * In the case of a forced ratelimit_gc, there will be no entries left 380*744bfb21SJohn Baldwin * so we will will not schedule another GC. */ 381*744bfb21SJohn Baldwin if (rl->rl_table_num > 0 && !callout_pending(&rl->rl_gc)) 382*744bfb21SJohn Baldwin callout_reset(&rl->rl_gc, ELEMENT_TIMEOUT * hz, 383*744bfb21SJohn Baldwin ratelimit_gc_callout, rl); 384*744bfb21SJohn Baldwin } 385*744bfb21SJohn Baldwin 386*744bfb21SJohn Baldwin static void 387*744bfb21SJohn Baldwin ratelimit_gc(struct ratelimit *rl, bool force) 388*744bfb21SJohn Baldwin { 389*744bfb21SJohn Baldwin size_t i; 390*744bfb21SJohn Baldwin struct ratelimit_entry *r, *tr; 391*744bfb21SJohn Baldwin sbintime_t expiry; 392*744bfb21SJohn Baldwin 393*744bfb21SJohn Baldwin mtx_assert(&rl->rl_mtx, MA_OWNED); 394*744bfb21SJohn Baldwin 395*744bfb21SJohn Baldwin if (rl->rl_table_num == 0) 396*744bfb21SJohn Baldwin return; 397*744bfb21SJohn Baldwin 398*744bfb21SJohn Baldwin expiry = getsbinuptime() - ELEMENT_TIMEOUT * SBT_1S; 399*744bfb21SJohn Baldwin 400*744bfb21SJohn Baldwin for (i = 0; i < RATELIMIT_SIZE; i++) { 401*744bfb21SJohn Baldwin LIST_FOREACH_SAFE(r, &rl->rl_table[i], r_entry, tr) { 402*744bfb21SJohn Baldwin if (r->r_last_time < expiry || force) { 403*744bfb21SJohn Baldwin rl->rl_table_num--; 404*744bfb21SJohn Baldwin LIST_REMOVE(r, r_entry); 405*744bfb21SJohn Baldwin uma_zfree(ratelimit_zone, r); 406*744bfb21SJohn Baldwin } 407*744bfb21SJohn Baldwin } 408*744bfb21SJohn Baldwin } 409*744bfb21SJohn Baldwin 410*744bfb21SJohn Baldwin ratelimit_gc_schedule(rl); 411*744bfb21SJohn Baldwin } 412*744bfb21SJohn Baldwin 413*744bfb21SJohn Baldwin static int 414*744bfb21SJohn Baldwin ratelimit_allow(struct ratelimit *rl, struct sockaddr *sa, struct vnet *vnet) 415*744bfb21SJohn Baldwin { 416*744bfb21SJohn Baldwin uint64_t bucket, tokens; 417*744bfb21SJohn Baldwin sbintime_t diff, now; 418*744bfb21SJohn Baldwin struct ratelimit_entry *r; 419*744bfb21SJohn Baldwin int ret = ECONNREFUSED; 420*744bfb21SJohn Baldwin struct ratelimit_key key = { .vnet = vnet }; 421*744bfb21SJohn Baldwin size_t len = sizeof(key); 422*744bfb21SJohn Baldwin 423*744bfb21SJohn Baldwin if (sa->sa_family == AF_INET) { 424*744bfb21SJohn Baldwin memcpy(key.ip, &satosin(sa)->sin_addr, IPV4_MASK_SIZE); 425*744bfb21SJohn Baldwin len -= IPV6_MASK_SIZE - IPV4_MASK_SIZE; 426*744bfb21SJohn Baldwin } 427*744bfb21SJohn Baldwin #ifdef INET6 428*744bfb21SJohn Baldwin else if (sa->sa_family == AF_INET6) 429*744bfb21SJohn Baldwin memcpy(key.ip, &satosin6(sa)->sin6_addr, IPV6_MASK_SIZE); 430*744bfb21SJohn Baldwin #endif 431*744bfb21SJohn Baldwin else 432*744bfb21SJohn Baldwin return ret; 433*744bfb21SJohn Baldwin 434*744bfb21SJohn Baldwin bucket = siphash13(rl->rl_secret, &key, len) & RATELIMIT_MASK; 435*744bfb21SJohn Baldwin mtx_lock(&rl->rl_mtx); 436*744bfb21SJohn Baldwin 437*744bfb21SJohn Baldwin LIST_FOREACH(r, &rl->rl_table[bucket], r_entry) { 438*744bfb21SJohn Baldwin if (bcmp(&r->r_key, &key, len) != 0) 439*744bfb21SJohn Baldwin continue; 440*744bfb21SJohn Baldwin 441*744bfb21SJohn Baldwin /* If we get to here, we've found an entry for the endpoint. 442*744bfb21SJohn Baldwin * We apply standard token bucket, by calculating the time 443*744bfb21SJohn Baldwin * lapsed since our last_time, adding that, ensuring that we 444*744bfb21SJohn Baldwin * cap the tokens at TOKEN_MAX. If the endpoint has no tokens 445*744bfb21SJohn Baldwin * left (that is tokens <= INITIATION_COST) then we block the 446*744bfb21SJohn Baldwin * request, otherwise we subtract the INITITIATION_COST and 447*744bfb21SJohn Baldwin * return OK. */ 448*744bfb21SJohn Baldwin now = getsbinuptime(); 449*744bfb21SJohn Baldwin diff = now - r->r_last_time; 450*744bfb21SJohn Baldwin r->r_last_time = now; 451*744bfb21SJohn Baldwin 452*744bfb21SJohn Baldwin tokens = r->r_tokens + diff; 453*744bfb21SJohn Baldwin 454*744bfb21SJohn Baldwin if (tokens > TOKEN_MAX) 455*744bfb21SJohn Baldwin tokens = TOKEN_MAX; 456*744bfb21SJohn Baldwin 457*744bfb21SJohn Baldwin if (tokens >= INITIATION_COST) { 458*744bfb21SJohn Baldwin r->r_tokens = tokens - INITIATION_COST; 459*744bfb21SJohn Baldwin goto ok; 460*744bfb21SJohn Baldwin } else { 461*744bfb21SJohn Baldwin r->r_tokens = tokens; 462*744bfb21SJohn Baldwin goto error; 463*744bfb21SJohn Baldwin } 464*744bfb21SJohn Baldwin } 465*744bfb21SJohn Baldwin 466*744bfb21SJohn Baldwin /* If we get to here, we didn't have an entry for the endpoint, let's 467*744bfb21SJohn Baldwin * add one if we have space. */ 468*744bfb21SJohn Baldwin if (rl->rl_table_num >= RATELIMIT_SIZE_MAX) 469*744bfb21SJohn Baldwin goto error; 470*744bfb21SJohn Baldwin 471*744bfb21SJohn Baldwin /* Goto error if out of memory */ 472*744bfb21SJohn Baldwin if ((r = uma_zalloc(ratelimit_zone, M_NOWAIT | M_ZERO)) == NULL) 473*744bfb21SJohn Baldwin goto error; 474*744bfb21SJohn Baldwin 475*744bfb21SJohn Baldwin rl->rl_table_num++; 476*744bfb21SJohn Baldwin 477*744bfb21SJohn Baldwin /* Insert entry into the hashtable and ensure it's initialised */ 478*744bfb21SJohn Baldwin LIST_INSERT_HEAD(&rl->rl_table[bucket], r, r_entry); 479*744bfb21SJohn Baldwin r->r_key = key; 480*744bfb21SJohn Baldwin r->r_last_time = getsbinuptime(); 481*744bfb21SJohn Baldwin r->r_tokens = TOKEN_MAX - INITIATION_COST; 482*744bfb21SJohn Baldwin 483*744bfb21SJohn Baldwin /* If we've added a new entry, let's trigger GC. */ 484*744bfb21SJohn Baldwin ratelimit_gc_schedule(rl); 485*744bfb21SJohn Baldwin ok: 486*744bfb21SJohn Baldwin ret = 0; 487*744bfb21SJohn Baldwin error: 488*744bfb21SJohn Baldwin mtx_unlock(&rl->rl_mtx); 489*744bfb21SJohn Baldwin return ret; 490*744bfb21SJohn Baldwin } 491*744bfb21SJohn Baldwin 492*744bfb21SJohn Baldwin static uint64_t siphash13(const uint8_t key[SIPHASH_KEY_LENGTH], const void *src, size_t len) 493*744bfb21SJohn Baldwin { 494*744bfb21SJohn Baldwin SIPHASH_CTX ctx; 495*744bfb21SJohn Baldwin return (SipHashX(&ctx, 1, 3, key, src, len)); 496*744bfb21SJohn Baldwin } 497*744bfb21SJohn Baldwin 498*744bfb21SJohn Baldwin #ifdef SELFTESTS 499*744bfb21SJohn Baldwin #include "selftest/cookie.c" 500*744bfb21SJohn Baldwin #endif /* SELFTESTS */ 501