From 4ee64aa978208207d48c82f9533054056802dd0e Mon Sep 17 00:00:00 2001 From: henning Date: Thu, 8 Feb 2018 09:15:46 +0000 Subject: [PATCH] make the watermarks/thresholds for entering and leaving syncookie mode when syncookies are set to adaptive tunable, ok claudio benno --- sbin/pfctl/parse.y | 41 ++++++++++++++++++++++++-- sbin/pfctl/pfctl.c | 62 ++++++++++++++++++++++++++++++--------- sbin/pfctl/pfctl_parser.h | 7 +++-- sys/net/pf_syncookies.c | 6 ++-- sys/net/pfvar.h | 5 +++- 5 files changed, 98 insertions(+), 23 deletions(-) diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index 6e20794156e..af2a9fedb4c 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.669 2018/02/06 23:47:47 henning Exp $ */ +/* $OpenBSD: parse.y,v 1.670 2018/02/08 09:15:46 henning Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -342,6 +342,7 @@ struct table_opts { struct node_hfsc_opts hfsc_opts; struct node_state_opt *keep_state_defaults = NULL; +struct pfctl_watermarks syncookie_opts; int disallow_table(struct node_host *, const char *); int disallow_urpf_failed(struct node_host *, const char *); @@ -449,6 +450,7 @@ typedef struct { struct table_opts table_opts; struct pool_opts pool_opts; struct node_hfsc_opts hfsc_opts; + struct pfctl_watermarks *watermarks; } v; int lineno; } YYSTYPE; @@ -527,6 +529,7 @@ int parseport(char *, struct range *r, int); %type scrub_opts scrub_opt scrub_opts_l %type table_opts table_opt table_opts_l %type pool_opts pool_opt pool_opts_l +%type syncookie_opts %% ruleset : /* empty */ @@ -686,8 +689,8 @@ option : SET REASSEMBLE yesno optnodf { } keep_state_defaults = $3; } - | SET SYNCOOKIES syncookie_val { - if (pfctl_set_syncookies(pf, $3)) { + | SET SYNCOOKIES syncookie_val syncookie_opts { + if (pfctl_set_syncookies(pf, $3, $4)) { yyerror("error setting syncookies"); YYERROR; } @@ -708,6 +711,38 @@ syncookie_val : STRING { } ; +syncookie_opts : /* empty */ { $$ = NULL; } + | { + memset(&syncookie_opts, 0, sizeof(syncookie_opts)); + } '(' syncookie_opt_l ')' { $$ = &syncookie_opts; } + ; + +syncookie_opt_l : syncookie_opt_l comma syncookie_opt + | syncookie_opt + ; + +syncookie_opt : STRING STRING { + double val; + char *cp; + + val = strtod($2, &cp); + if (cp == NULL || strcmp(cp, "%")) + YYERROR; + if (val <= 0 || val > 100) { + yyerror("illegal percentage value"); + YYERROR; + } + if (!strcmp($1, "start")) { + syncookie_opts.hi = val; + } else if (!strcmp($1, "end")) { + syncookie_opts.lo = val; + } else { + yyerror("illegal syncookie option"); + YYERROR; + } + } + ; + stringall : STRING { $$ = $1; } | ALL { if (($$ = strdup("all")) == NULL) { diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c index 141c94fbf94..93ca9215bf0 100644 --- a/sbin/pfctl/pfctl.c +++ b/sbin/pfctl/pfctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl.c,v 1.353 2018/02/08 02:26:39 henning Exp $ */ +/* $OpenBSD: pfctl.c,v 1.354 2018/02/08 09:15:46 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -1752,6 +1752,9 @@ pfctl_init_options(struct pfctl *pf) pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT; + pf->syncookieswat[0] = PF_SYNCOOKIES_LOWATPCT; + pf->syncookieswat[1] = PF_SYNCOOKIES_HIWATPCT; + mib[0] = CTL_KERN; mib[1] = KERN_MAXCLUSTERS; size = sizeof(mcl); @@ -1801,15 +1804,6 @@ pfctl_load_options(struct pfctl *pf) pf->timeout_set[PFTM_ADAPTIVE_END] = 1; } - /* - * if the states limit has been set adjust the synflood detection - * hiwat and lowat. Eventually they should be tunables. - */ - if (pf->limit_set[PF_LIMIT_STATES]) - if (pfctl_set_synflwats(pf, pf->limit[PF_LIMIT_STATES] / 8, - pf->limit[PF_LIMIT_STATES] / 4)) - error = 1; - /* load timeouts */ for (i = 0; i < PFTM_MAX; i++) if (pfctl_load_timeout(pf, i, pf->timeout[i])) @@ -1834,6 +1828,23 @@ pfctl_load_options(struct pfctl *pf) /* load syncookies settings */ if (pf->syncookies_set && pfctl_load_syncookies(pf, pf->syncookies)) error = 1; + if (pf->syncookieswat_set) { + struct pfioc_limit pl; + unsigned curlim; + + if (pf->limit_set[PF_LIMIT_STATES]) + curlim = pf->limit[PF_LIMIT_STATES]; + else { + memset(&pl, 0, sizeof(pl)); + pl.index = pf_limits[PF_LIMIT_STATES].index; + if (ioctl(dev, DIOCGETLIMIT, &pl)) + err(1, "DIOCGETLIMIT"); + curlim = pl.limit; + } + if (pfctl_set_synflwats(pf, curlim * pf->syncookieswat[0]/100, + curlim * pf->syncookieswat[1]/100)) + error = 1; + } return (error); } @@ -1958,16 +1969,39 @@ pfctl_set_reassembly(struct pfctl *pf, int on, int nodf) } int -pfctl_set_syncookies(struct pfctl *pf, u_int8_t val) +pfctl_set_syncookies(struct pfctl *pf, u_int8_t val, struct pfctl_watermarks *w) { + if (val != PF_SYNCOOKIES_ADAPTIVE && w != NULL) { + warnx("syncookies start/end only apply to adaptive"); + return (1); + } + if (val == PF_SYNCOOKIES_ADAPTIVE && w != NULL) { + if (!w->hi) + w->hi = PF_SYNCOOKIES_HIWATPCT; + if (!w->lo) + w->lo = w->hi / 2; + if (w->lo >= w->hi) { + warnx("start must be higher than end"); + return (1); + } + pf->syncookieswat[0] = w->lo; + pf->syncookieswat[1] = w->hi; + pf->syncookieswat_set = 1; + } + if (pf->opts & PF_OPT_VERBOSE) { if (val == PF_SYNCOOKIES_NEVER) printf("set syncookies never\n"); else if (val == PF_SYNCOOKIES_ALWAYS) printf("set syncookies always\n"); - else if (val == PF_SYNCOOKIES_ADAPTIVE) - printf("set syncookies adaptive\n"); - else { /* cannot happen */ + else if (val == PF_SYNCOOKIES_ADAPTIVE) { + if (pf->syncookieswat_set) + printf("set syncookies adaptive (start %u%%, " + "end %u%%)\n", pf->syncookieswat[1], + pf->syncookieswat[0]); + else + printf("set syncookies adaptive\n"); + } else { /* cannot happen */ warnx("king bula ate all syncookies"); return (1); } diff --git a/sbin/pfctl/pfctl_parser.h b/sbin/pfctl/pfctl_parser.h index ef42d864c24..eefeb19e6b4 100644 --- a/sbin/pfctl/pfctl_parser.h +++ b/sbin/pfctl/pfctl_parser.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_parser.h,v 1.109 2018/02/08 02:26:39 henning Exp $ */ +/* $OpenBSD: pfctl_parser.h,v 1.110 2018/02/08 09:15:46 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -92,6 +92,7 @@ struct pfctl { u_int32_t hostid; u_int32_t reassemble; u_int8_t syncookies; + u_int8_t syncookieswat[2]; /* lowat, hiwat */ char *ifname; u_int8_t timeout_set[PFTM_MAX]; @@ -101,6 +102,7 @@ struct pfctl { u_int8_t ifname_set; u_int8_t reass_set; u_int8_t syncookies_set; + u_int8_t syncookieswat_set; }; struct node_if { @@ -221,7 +223,8 @@ void pfctl_clear_pool(struct pf_pool *); int pfctl_set_timeout(struct pfctl *, const char *, int, int); int pfctl_set_reassembly(struct pfctl *, int, int); -int pfctl_set_syncookies(struct pfctl *, u_int8_t); +int pfctl_set_syncookies(struct pfctl *, u_int8_t, + struct pfctl_watermarks *); int pfctl_set_optimization(struct pfctl *, const char *); int pfctl_set_limit(struct pfctl *, const char *, unsigned int); int pfctl_set_logif(struct pfctl *, char *); diff --git a/sys/net/pf_syncookies.c b/sys/net/pf_syncookies.c index 14becfb2b30..63d15f12bc2 100644 --- a/sys/net/pf_syncookies.c +++ b/sys/net/pf_syncookies.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_syncookies.c,v 1.4 2018/02/08 02:25:44 henning Exp $ */ +/* $OpenBSD: pf_syncookies.c,v 1.5 2018/02/08 09:15:46 henning Exp $ */ /* Copyright (c) 2016,2017 Henning Brauer * Copyright (c) 2016 Alexandr Nedvedicky @@ -132,8 +132,8 @@ pf_syncookies_init(void) { timeout_set(&pf_syncookie_status.keytimeout, pf_syncookie_rotate, NULL); - pf_syncookie_status.hiwat = PFSTATE_HIWAT/4; - pf_syncookie_status.lowat = PFSTATE_HIWAT/8; + pf_syncookie_status.hiwat = PFSTATE_HIWAT * PF_SYNCOOKIES_HIWATPCT/100; + pf_syncookie_status.lowat = PFSTATE_HIWAT * PF_SYNCOOKIES_LOWATPCT/100; pf_syncookies_setmode(PF_SYNCOOKIES_NEVER); } diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index 7ec2d91da41..fb245426ef4 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfvar.h,v 1.473 2018/02/08 02:25:44 henning Exp $ */ +/* $OpenBSD: pfvar.h,v 1.474 2018/02/08 09:15:46 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -1326,6 +1326,9 @@ struct pf_status { #define PF_SYNCOOKIES_ADAPTIVE 2 #define PF_SYNCOOKIES_MODE_MAX PF_SYNCOOKIES_ADAPTIVE +#define PF_SYNCOOKIES_HIWATPCT 25 +#define PF_SYNCOOKIES_LOWATPCT PF_SYNCOOKIES_HIWATPCT/2 + #define PF_PRIO_ZERO 0xff /* match "prio 0" packets */ struct pf_queue_bwspec { -- 2.20.1