* Ed White <[EMAIL PROTECTED]> [19.01.2004 16:14]:
> I would like to know if there is any plan to limit the number of bytes
> a TCP connection can transfer. The idea is to drop/close the
> connection after $SIZE bytes have been transferred. 

This is a first cut at this idea. It implements a per-state traffic
limit like this:

    pass in proto tcp from any to any port = 25 \
        flags S/SA keep state (bytes 100000)

This could be easily extended to per-rule or per-source-ip limits. I
just didn't want to invent too many keywords.

Opinions? Ideas?


Index: sys/net/pf.c
===================================================================
RCS file: /cvs/src/sys/net/pf.c,v
retrieving revision 1.418
diff -p -u -r1.418 pf.c
--- sys/net/pf.c        6 Jan 2004 20:24:33 -0000       1.418
+++ sys/net/pf.c        21 Jan 2004 15:54:19 -0000
@@ -5469,6 +5469,12 @@ done:
                REASON_SET(&reason, PFRES_MEMORY);
        }
 
+       if (r->max_bytes && (s->bytes[0] + s->bytes[1] >= r->max_bytes)) {
+               s->timeout = PFTM_PURGE;
+               action = PF_DROP;
+               REASON_SET(&reason, PFRES_MAXBYTES);
+       }
+
        if (log)
                PFLOG_PACKET(kif, h, m, AF_INET, dir, reason, r, a, ruleset);
 
Index: sys/net/pfvar.h
===================================================================
RCS file: /cvs/src/sys/net/pfvar.h,v
retrieving revision 1.180
diff -p -u -r1.180 pfvar.h
--- sys/net/pfvar.h     31 Dec 2003 11:18:25 -0000      1.180
+++ sys/net/pfvar.h     21 Jan 2004 15:54:19 -0000
@@ -484,6 +484,7 @@ struct pf_rule {
        u_int32_t                timeout[PFTM_MAX];
        u_int32_t                states;
        u_int32_t                max_states;
+       u_int64_t                max_bytes;
        u_int32_t                src_nodes;
        u_int32_t                max_src_nodes;
        u_int32_t                max_src_states;
@@ -859,7 +860,8 @@ struct pf_pdesc {
 #define PFRES_SHORT    3               /* Dropping short packet */
 #define PFRES_NORM     4               /* Dropping by normalizer */
 #define PFRES_MEMORY   5               /* Dropped due to lacking mem */
-#define PFRES_MAX      6               /* total+1 */
+#define PFRES_MAXBYTES 6               /* Dropped due to bytes limit */
+#define PFRES_MAX      7               /* total+1 */
 
 #define PFRES_NAMES { \
        "match", \
@@ -868,6 +870,7 @@ struct pf_pdesc {
        "short", \
        "normalize", \
        "memory", \
+       "bytes", \
        NULL \
 }
 
Index: sbin/pfctl/parse.y
===================================================================
RCS file: /cvs/src/sbin/pfctl/parse.y,v
retrieving revision 1.436
diff -p -u -r1.436 parse.y
--- sbin/pfctl/parse.y  5 Jan 2004 22:04:24 -0000       1.436
+++ sbin/pfctl/parse.y  21 Jan 2004 15:53:57 -0000
@@ -117,12 +117,13 @@ struct node_icmp {
 
 enum   { PF_STATE_OPT_MAX, PF_STATE_OPT_NOSYNC, PF_STATE_OPT_SRCTRACK,
          PF_STATE_OPT_MAX_SRC_STATES, PF_STATE_OPT_MAX_SRC_NODES,
-         PF_STATE_OPT_STATELOCK, PF_STATE_OPT_TIMEOUT };
+         PF_STATE_OPT_STATELOCK, PF_STATE_OPT_TIMEOUT, PF_STATE_OPT_BYTES };
 
 struct node_state_opt {
        int                      type;
        union {
                u_int32_t        max_states;
+               u_int64_t        max_bytes;
                u_int32_t        max_src_states;
                u_int32_t        max_src_nodes;
                u_int8_t         src_track;
@@ -399,7 +400,7 @@ typedef struct {
 %token QUEUE PRIORITY QLIMIT
 %token LOAD
 %token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE
-%token TAGGED TAG IFBOUND GRBOUND FLOATING STATEPOLICY
+%token TAGGED TAG IFBOUND GRBOUND FLOATING STATEPOLICY BYTES
 %token <v.string>              STRING
 %token <v.i>                   PORTBINARY
 %type  <v.interface>           interface if_list if_item_not if_item
@@ -1465,6 +1466,14 @@ pfrule           : action dir logquick interface 
                                        }
                                        r.max_states = o->data.max_states;
                                        break;
+                               case PF_STATE_OPT_BYTES:
+                                       if (r.max_bytes) {
+                                               yyerror("state option 'bytes' "
+                                                   "multiple definitions");
+                                               YYERROR;
+                                       }
+                                       r.max_bytes = o->data.max_bytes;
+                                       break;
                                case PF_STATE_OPT_NOSYNC:
                                        if (r.rule_flag & PFRULE_NOSYNC) {
                                                yyerror("state option 'sync' "
@@ -2571,6 +2580,15 @@ state_opt_item   : MAXIMUM number                {
                        $$->next = NULL;
                        $$->tail = $$;
                }
+               | BYTES number          {
+                       $$ = calloc(1, sizeof(struct node_state_opt));
+                       if ($$ == NULL)
+                               err(1, "state_opt_item: calloc");
+                       $$->type = PF_STATE_OPT_BYTES;
+                       $$->data.max_bytes = $2;
+                       $$->next = NULL;
+                       $$->tail = $$;
+               }
                | NOSYNC                                {
                        $$ = calloc(1, sizeof(struct node_state_opt));
                        if ($$ == NULL)
@@ -4131,6 +4149,7 @@ lookup(char *s)
                { "bitmask",            BITMASK},
                { "block",              BLOCK},
                { "block-policy",       BLOCKPOLICY},
+               { "bytes",              BYTES},
                { "cbq",                CBQ},
                { "code",               CODE},
                { "crop",               FRAGCROP},
Index: sbin/pfctl/pfctl_parser.c
===================================================================
RCS file: /cvs/src/sbin/pfctl/pfctl_parser.c,v
retrieving revision 1.187
diff -p -u -r1.187 pfctl_parser.c
--- sbin/pfctl/pfctl_parser.c   31 Dec 2003 22:14:41 -0000      1.187
+++ sbin/pfctl/pfctl_parser.c   21 Jan 2004 15:53:57 -0000
@@ -776,7 +776,7 @@ print_rule(struct pf_rule *r, int verbos
        else if (r->keep_state == PF_STATE_SYNPROXY)
                printf(" synproxy state");
        opts = 0;
-       if (r->max_states || r->max_src_nodes || r->max_src_states)
+       if (r->max_states || r->max_src_nodes || r->max_src_states || r->max_bytes)
                opts = 1;
        if (r->rule_flag & PFRULE_NOSYNC)
                opts = 1;
@@ -791,6 +791,12 @@ print_rule(struct pf_rule *r, int verbos
                printf(" (");
                if (r->max_states) {
                        printf("max %u", r->max_states);
+                       opts = 0;
+               }
+               if (r->max_bytes) {
+                       if (!opts)
+                               printf(", ");
+                       printf("bytes %llu", r->max_bytes);
                        opts = 0;
                }
                if (r->rule_flag & PFRULE_NOSYNC) {

Reply via email to