allow control over syncookies: set syncookies never/always/adaptive
authorhenning <henning@openbsd.org>
Tue, 6 Feb 2018 23:47:47 +0000 (23:47 +0000)
committerhenning <henning@openbsd.org>
Tue, 6 Feb 2018 23:47:47 +0000 (23:47 +0000)
sbin/pfctl/parse.y
sbin/pfctl/pfctl.c
sbin/pfctl/pfctl_parser.h

index 06615c9..6e20794 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: parse.y,v 1.668 2017/11/28 16:05:46 bluhm Exp $       */
+/*     $OpenBSD: parse.y,v 1.669 2018/02/06 23:47:47 henning Exp $     */
 
 /*
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
@@ -468,7 +468,7 @@ int parseport(char *, struct range *r, int);
 %token ICMP6TYPE CODE KEEP MODULATE STATE PORT BINATTO NODF
 %token MINTTL ERROR ALLOWOPTS FILENAME ROUTETO DUPTO REPLYTO NO LABEL
 %token NOROUTE URPFFAILED FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE
-%token REASSEMBLE ANCHOR
+%token REASSEMBLE ANCHOR SYNCOOKIES
 %token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY RANDOMID
 %token SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID
 %token ANTISPOOF FOR INCLUDE MATCHES
@@ -488,7 +488,7 @@ int parseport(char *, struct range *r, int);
 %type  <v.number>              tos not yesno optnodf
 %type  <v.probability>         probability
 %type  <v.weight>              optweight
-%type  <v.i>                   dir af optimizer
+%type  <v.i>                   dir af optimizer syncookie_val
 %type  <v.i>                   sourcetrack flush unaryop statelock
 %type  <v.b>                   action
 %type  <v.b>                   flags flag blockspec prio
@@ -686,6 +686,26 @@ option             : SET REASSEMBLE yesno optnodf          {
                        }
                        keep_state_defaults = $3;
                }
+               | SET SYNCOOKIES syncookie_val {
+                       if (pfctl_set_syncookies(pf, $3)) {
+                               yyerror("error setting syncookies");
+                               YYERROR;
+                       }
+               }
+               ;
+
+syncookie_val  : STRING        {
+                       if (!strcmp($1, "never"))
+                               $$ = PF_SYNCOOKIES_NEVER;
+                       else if (!strcmp($1, "adaptive"))
+                               $$ = PF_SYNCOOKIES_ADAPTIVE;
+                       else if (!strcmp($1, "always"))
+                               $$ = PF_SYNCOOKIES_ALWAYS;
+                       else {
+                               yyerror("illegal value for syncookies");
+                               YYERROR;
+                       }
+               }
                ;
 
 stringall      : STRING        { $$ = $1; }
@@ -5148,6 +5168,7 @@ lookup(char *s)
                { "state-policy",       STATEPOLICY},
                { "static-port",        STATICPORT},
                { "sticky-address",     STICKYADDRESS},
+               { "syncookies",         SYNCOOKIES},
                { "synproxy",           SYNPROXY},
                { "table",              TABLE},
                { "tag",                TAG},
index 6c66aa5..20df20f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pfctl.c,v 1.351 2017/11/25 22:26:25 sashan Exp $ */
+/*     $OpenBSD: pfctl.c,v 1.352 2018/02/06 23:47:47 henning Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -81,6 +81,8 @@ int    pfctl_load_debug(struct pfctl *, unsigned int);
 int     pfctl_load_logif(struct pfctl *, char *);
 int     pfctl_load_hostid(struct pfctl *, unsigned int);
 int     pfctl_load_reassembly(struct pfctl *, u_int32_t);
+int     pfctl_load_syncookies(struct pfctl *, u_int8_t);
+int     pfctl_set_synflwats(struct pfctl *, u_int32_t, u_int32_t);
 void    pfctl_print_rule_counters(struct pf_rule *, int);
 int     pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int, int,
            long);
@@ -1791,6 +1793,15 @@ 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]))
@@ -1812,6 +1823,10 @@ pfctl_load_options(struct pfctl *pf)
        if (pf->reass_set && pfctl_load_reassembly(pf, pf->reassemble))
                error = 1;
 
+       /* load syncookies settings */
+       if (pf->syncookies_set && pfctl_load_syncookies(pf, pf->syncookies))
+               error = 1;
+
        return (error);
 }
 
@@ -1899,6 +1914,22 @@ pfctl_load_timeout(struct pfctl *pf, unsigned int timeout, unsigned int seconds)
        return (0);
 }
 
+int
+pfctl_set_synflwats(struct pfctl *pf, u_int32_t lowat, u_int32_t hiwat)
+{
+       struct pfioc_synflwats ps;
+
+       memset(&ps, 0, sizeof(ps));
+       ps.hiwat = hiwat;
+       ps.lowat = lowat;
+
+       if (ioctl(pf->dev, DIOCSETSYNFLWATS, &ps)) {
+               warnx("Cannot set synflood detection watermarks");
+               return (1);
+       }
+       return (0);
+}
+
 int
 pfctl_set_reassembly(struct pfctl *pf, int on, int nodf)
 {
@@ -1918,6 +1949,27 @@ pfctl_set_reassembly(struct pfctl *pf, int on, int nodf)
        return (0);
 }
 
+int
+pfctl_set_syncookies(struct pfctl *pf, u_int8_t val)
+{
+       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 */
+                       warnx("king bula ate all syncookies");
+                       return (1);
+               }
+       }
+
+       pf->syncookies_set = 1;
+       pf->syncookies = val;
+       return (0);
+}
+
 int
 pfctl_set_optimization(struct pfctl *pf, const char *opt)
 {
@@ -2014,6 +2066,16 @@ pfctl_load_reassembly(struct pfctl *pf, u_int32_t reassembly)
        return (0);
 }
 
+int
+pfctl_load_syncookies(struct pfctl *pf, u_int8_t val)
+{
+       if (ioctl(dev, DIOCSETSYNCOOKIES, &val)) {
+               warnx("DIOCSETSYNCOOKIES");
+               return (1);
+       }
+       return (0);
+}
+
 int
 pfctl_set_debug(struct pfctl *pf, char *d)
 {
index 08539b1..9c30184 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pfctl_parser.h,v 1.107 2017/11/25 22:20:06 sashan Exp $ */
+/*     $OpenBSD: pfctl_parser.h,v 1.108 2018/02/06 23:47:47 henning Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -91,6 +91,7 @@ struct pfctl {
        u_int32_t        debug;
        u_int32_t        hostid;
        u_int32_t        reassemble;
+       u_int8_t         syncookies;
        char            *ifname;
 
        u_int8_t         timeout_set[PFTM_MAX];
@@ -99,6 +100,7 @@ struct pfctl {
        u_int8_t         hostid_set;
        u_int8_t         ifname_set;
        u_int8_t         reass_set;
+       u_int8_t         syncookies_set;
 };
 
 struct node_if {
@@ -215,6 +217,7 @@ 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_optimization(struct pfctl *, const char *);
 int    pfctl_set_limit(struct pfctl *, const char *, unsigned int);
 int    pfctl_set_logif(struct pfctl *, char *);