* 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 10)
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.c6 Jan 2004 20:24:33 - 1.418
+++ sys/net/pf.c21 Jan 2004 15:54:19 -
@@ -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 - 1.180
+++ sys/net/pfvar.h 21 Jan 2004 15:54:19 -
@@ -484,6 +484,7 @@ struct pf_rule {
u_int32_ttimeout[PFTM_MAX];
u_int32_tstates;
u_int32_tmax_states;
+ u_int64_tmax_bytes;
u_int32_tsrc_nodes;
u_int32_tmax_src_nodes;
u_int32_tmax_src_states;
@@ -859,7 +860,8 @@ struct pf_pdesc {
#define PFRES_SHORT3 /* 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 - 1.436
+++ sbin/pfctl/parse.y 21 Jan 2004 15:53:57 -
@@ -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_tmax_states;
+ u_int64_tmax_bytes;
u_int32_tmax_src_states;
u_int32_tmax_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 {
+