--- extensions/Makefile.orig 2005-07-13 15:25:35.000000000 +0100 +++ extensions/Makefile 2005-07-13 15:25:54.000000000 +0100 @@ -6,8 +6,9 @@ # PF_EXT_SLIB:=ah addrtype comment connlimit connmark conntrack dscp ecn esp hashlimit helper icmp iprange length limit mac mark multiport owner physdev pkttype realm rpc sctp standard state tcp tcpmss tos ttl udp unclean CLASSIFY CONNMARK DNAT DSCP ECN LOG MARK MASQUERADE MIRROR NETMAP NFQUEUE NOTRACK REDIRECT REJECT SAME SNAT TARPIT TCPMSS TOS TRACE TTL ULOG layer7 PF_EXT_SLIB+=connrate ROUTE time account quota PF_EXT_SLIB+=condition +PF_EXT_SLIB+=recent PF_EXT_SLIB+=vlan PF6_EXT_SLIB:=eui64 hl icmpv6 length limit mac mark multiport owner physdev standard tcp udp HL LOG NFQUEUE MARK TRACE # Optionals --- extensions/libipt_recent.man.orig 2006-03-01 12:39:29.000000000 +0000 +++ extensions/libipt_recent.man 2006-03-02 10:40:53.000000000 +0000 @@ -9,6 +9,63 @@ Specify the list to use for the commands. If no name is given then 'DEFAULT' will be used. .TP +[\fB!\fR] \fB--listcount-lt \ficount\fR +Requires as a precondition that the number of IP entries in the list +(subject to the optional --listtime-* specifier) +is less than count (or not !). No other options are considered if +this is not true. +.TP +[\fB!\fR] \fB--listcount-le \ficount\fR +Requires as a precondition that the number of IP entries in the list +(subject to the optional --listtime-* specifier) +is less than or equal to count (or not !). No other options are considered if +this is not true. +.TP +[\fB!\fR] \fB--listcount-eq \ficount\fR +Requires as a precondition that the number of IP entries in the list +(subject to the optional --listtime-* specifier) +is equal to (or not !) count. No other options are considered if +this is not true. +.TP +[\fB!\fR] \fB--listcount-ge \ficount\fR +Requires as a precondition that the number of IP entries in the list +(subject to the optional --listtime-* specifier) +is greater than or equal to count (or not !). No other options are considered if +this is not true. +.TP +[\fB!\fR] \fB--listcount-gt \ficount\fR +Requires as a precondition that the number of IP entries in the list +(subject to the optional --listtime-* specifier) +is greater than count (or not !). No other options are considered if +this is not true. +.TP +Only one --listcount-* option can be specified. +.TP +[\fB!\fR] \fB--listtime-lt \fisecounds\fR +Affects the --listcount-* so that instead of counting the number of +items in the list, it counts the number of items that were last updated +less than \fBseconds\fR seconds ago. +.TP +[\fB!\fR] \fB--listtime-le \fisecounds\fR +Affects the --listcount-* so that instead of counting the number of +items in the list, it counts the number of items that were last updated +less than or equal to \fBseconds\fR seconds ago. +.TP +[\fB!\fR] \fB--listtime-ge \fisecounds\fR +Affects the --listcount-* so that instead of counting the number of +items in the list, it counts the number of items that were last updated +more than or equal to \fBseconds\fR seconds ago. +.TP +[\fB!\fR] \fB--listtime-gt \fisecounds\fR +Affects the --listcount-* so that instead of counting the number of +items in the list, it counts the number of items that were last updated +more than \fBseconds\fR seconds ago. +.TP +Only one --listtime-* option can be specified. --listtime-* options act +as select clauses for what to count. The ! negation for --listtime-* +options merely inverts the comparison, so \fB! --listime-le\fR is the same as +\fB--listtime-gt\fR +.TP [\fB!\fR] \fB--set\fR This will add the source address of the packet to the list. If the source address is already in the list, this will update the existing @@ -56,6 +113,12 @@ # iptables -A FORWARD -m recent --name badguy --rcheck --seconds 60 -j DROP # iptables -A FORWARD -p tcp -i eth0 --dport 139 -m recent --name badguy --set -j DROP + +The next example accepts the packet if less than 5 ip addresses in the list have +been updated in the last 60 seconds + +# iptables -A FORWARD -m recent --listcount-lt 5 --listtime-lt 60 --set -j ACCEPT + .P Official website (http://snowman.net/projects/ipt_recent/) also has some examples of usage. --- extensions/libipt_recent.c.orig 2006-03-13 17:02:03.000000000 +0000 +++ extensions/libipt_recent.c 2006-03-13 17:19:25.000000000 +0000 @@ -23,17 +23,28 @@ /* Options for this module */ static struct option opts[] = { - { .name = "set", .has_arg = 0, .flag = 0, .val = 201 }, - { .name = "rcheck", .has_arg = 0, .flag = 0, .val = 202 }, - { .name = "update", .has_arg = 0, .flag = 0, .val = 203 }, - { .name = "seconds", .has_arg = 1, .flag = 0, .val = 204 }, - { .name = "hitcount", .has_arg = 1, .flag = 0, .val = 205 }, - { .name = "remove", .has_arg = 0, .flag = 0, .val = 206 }, - { .name = "rttl", .has_arg = 0, .flag = 0, .val = 207 }, - { .name = "name", .has_arg = 1, .flag = 0, .val = 208 }, - { .name = "rsource", .has_arg = 0, .flag = 0, .val = 209 }, - { .name = "rdest", .has_arg = 0, .flag = 0, .val = 210 }, - { .name = 0, .has_arg = 0, .flag = 0, .val = 0 } +#ifdef IPT_RECENT_HAS_LIST_OPS + { .name = "set", .has_arg = 0, .flag = 0, .val = 201 }, + { .name = "rcheck", .has_arg = 0, .flag = 0, .val = 202 }, + { .name = "update", .has_arg = 0, .flag = 0, .val = 203 }, + { .name = "seconds", .has_arg = 1, .flag = 0, .val = 204 }, + { .name = "hitcount", .has_arg = 1, .flag = 0, .val = 205 }, + { .name = "remove", .has_arg = 0, .flag = 0, .val = 206 }, + { .name = "rttl", .has_arg = 0, .flag = 0, .val = 207 }, + { .name = "name", .has_arg = 1, .flag = 0, .val = 208 }, + { .name = "rsource", .has_arg = 0, .flag = 0, .val = 209 }, + { .name = "rdest", .has_arg = 0, .flag = 0, .val = 210 }, + { .name = "listcount-lt", .has_arg = 1, .flag = 0, .val = 211 }, + { .name = "listcount-le", .has_arg = 1, .flag = 0, .val = 212 }, + { .name = "listcount-eq", .has_arg = 1, .flag = 0, .val = 213 }, + { .name = "listcount-ge", .has_arg = 1, .flag = 0, .val = 214 }, + { .name = "listcount-gt", .has_arg = 1, .flag = 0, .val = 215 }, + { .name = "listtime-lt", .has_arg = 1, .flag = 0, .val = 216 }, + { .name = "listtime-le", .has_arg = 1, .flag = 0, .val = 217 }, + { .name = "listtime-ge", .has_arg = 1, .flag = 0, .val = 218 }, + { .name = "listtime-gt", .has_arg = 1, .flag = 0, .val = 219 }, +#endif + { .name = 0, .has_arg = 0, .flag = 0, .val = 0 } }; /* Function which prints out usage message. */ @@ -42,6 +53,20 @@ { printf( "recent v%s options:\n" +#ifdef RECENT_HAS_LIST_OPS +" PRECONDITIONS Only one precondition may be set.\n" +"[!] --listcount-lt n Only match if there are less than n items in the table\n" +"[!] --listcount-le n Only match if there are n items or less in the table\n" +"[!] --listcount-eq n Only match if there are n items in the table\n" +"[!] --listcount-ge n Only match if there are n items or more in the table\n" +"[!] --listcount-gt n Only match if there are more than n items in the table\n" + +"[!] --listtimes-lt n --listcount option only applies to items less than n seconds old\n" +"[!] --listtimes-le n --listcount option only applies to items n seconds old or less\n" +"[!] --listtimes-ge n --listcount option only applies to items n seconds old or more\n" +"[!] --listtimes-gt n --listcount option only applies ti items more than n seconds old\n" +#endif +" The precondtion may be followed by:\n" "[!] --set Add source address to list, always matches.\n" "[!] --rcheck Match if source address in list.\n" "[!] --update Match if source address in list, also update last-seen time.\n" @@ -78,6 +103,11 @@ * better be safe, than sorry */ info->name[IPT_RECENT_NAME_LEN-1] = '\0'; info->side = IPT_RECENT_SOURCE; +/* If kernel side supports LIST_OPS but we don't set this flag it will + presume we are an old client side and refuse the rule */ +#ifdef IPT_RECENT_HAS_LIST_OPS + info->check_set |= IPT_RECENT_HAS_LIST_OPS; +#endif } /* Function which parses command options; returns true if it @@ -155,6 +185,89 @@ info->side = IPT_RECENT_DEST; break; +#ifdef IPT_RECENT_HAS_LIST_OPS + case 211: /* listcount-lt */ + if (info->count_ops & IPT_RECENT_COUNT_OPS) exit_error(PARAMETER_PROBLEM, + "recent: only one of `--listcount-lt', `--listcount-le' " + "`--listcount-eq', `--listcount-ge' `listcount-gts'` " + " or `--eq' may be set"); + info->count_ops |= IPT_RECENT_COUNT_LT | (invert?IPT_RECENT_COUNT_INVERT:0); + info->entry_count=atoi(optarg); + break; + + case 212: /* listcount-le */ + if (info->count_ops & IPT_RECENT_COUNT_OPS) exit_error(PARAMETER_PROBLEM, + "recent: only one of `--listcount-lt', `--listcount-le' " + "`--listcount-eq', `--listcount-ge' `listcount-gts'` " + " or `--eq' may be set"); + info->count_ops |= IPT_RECENT_COUNT_LE | (invert?IPT_RECENT_COUNT_INVERT:0); + info->entry_count=atoi(optarg); + break; + + case 213: /* listcount-eq */ + if (info->count_ops & IPT_RECENT_COUNT_OPS) exit_error(PARAMETER_PROBLEM, + "recent: only one of `--listcount-lt', `--listcount-le' " + "`--listcount-eq', `--listcount-ge' `listcount-gts'` " + " or `--eq' may be set"); + info->count_ops |= IPT_RECENT_COUNT_EQ | (invert?IPT_RECENT_COUNT_INVERT:0); + info->entry_count=atoi(optarg); + break; + + case 214: /* listcount-ge */ + if (info->count_ops & IPT_RECENT_COUNT_OPS) exit_error(PARAMETER_PROBLEM, + "recent: only one of `--listcount-lt', `--listcount-le' " + "`--listcount-eq', `--listcount-ge' `listcount-gts'` " + " or `--eq' may be set"); + info->count_ops |= IPT_RECENT_COUNT_GE | (invert?IPT_RECENT_COUNT_INVERT:0); + info->entry_count=atoi(optarg); + break; + + case 215: /* listcount-gt */ + if (info->count_ops & IPT_RECENT_COUNT_OPS) exit_error(PARAMETER_PROBLEM, + "recent: only one of `--listcount-lt', `--listcount-le' " + "`--listcount-eq', `--listcount-ge' `listcount-gts'` " + " or `--eq' may be set"); + info->count_ops |= IPT_RECENT_COUNT_GT | (invert?IPT_RECENT_COUNT_INVERT:0); + info->entry_count=atoi(optarg); + break; + + case 216: /* listtime-lt */ + if (info->count_ops & IPT_RECENT_TIME_OPS) exit_error(PARAMETER_PROBLEM, + "recent: only one of `--listtime-lt', `--listtime-le' " + "`--listtime-eq', `--listtime-ge' `listtime-gts'` " + " or `--eq' may be set"); + info->count_ops |= invert?IPT_RECENT_TIME_GE:IPT_RECENT_TIME_LT; + info->entry_time=atoi(optarg); + break; + + case 217: /* listtime-le */ + if (info->count_ops & IPT_RECENT_TIME_OPS) exit_error(PARAMETER_PROBLEM, + "recent: only one of `--listtime-lt', `--listtime-le' " + "`--listtime-eq', `--listtime-ge' `listtime-gts'` " + " or `--eq' may be set"); + info->count_ops |= invert?IPT_RECENT_TIME_GT:IPT_RECENT_TIME_LE; + info->entry_time=atoi(optarg); + break; + + case 218: /* listtime-ge */ + if (info->count_ops & IPT_RECENT_TIME_OPS) exit_error(PARAMETER_PROBLEM, + "recent: only one of `--listtime-lt', `--listtime-le' " + "`--listtime-eq', `--listtime-ge' `listtime-gts'` " + " or `--eq' may be set"); + info->count_ops |= invert?IPT_RECENT_TIME_LT:IPT_RECENT_TIME_GE; + info->entry_time=atoi(optarg); + break; + + case 219: /* listtime-gt */ + if (info->count_ops & IPT_RECENT_TIME_OPS) exit_error(PARAMETER_PROBLEM, + "recent: only one of `--listtime-lt', `--listtime-le' " + "`--listtime-eq', `--listtime-ge' `listtime-gts'` " + " or `--eq' may be set"); + info->count_ops |= invert?IPT_RECENT_TIME_LE:IPT_RECENT_TIME_GT; + info->entry_time=atoi(optarg); + break; +#endif + default: return 0; } @@ -181,10 +294,35 @@ { struct ipt_recent_info *info = (struct ipt_recent_info *)match->data; +#ifdef IPT_RECENT_HAS_LIST_OPS + printf("recent: "); + + /* handle the precondition first */ + if (info->count_ops) { + if (info->count_ops & IPT_RECENT_COUNT_INVERT) printf("not "); + switch (info->count_ops & IPT_RECENT_COUNT_OPS) { + case IPT_RECENT_COUNT_LT: printf("< "); break; + case IPT_RECENT_COUNT_LE: printf("<= "); break; + case IPT_RECENT_COUNT_EQ: printf("== "); break; + case IPT_RECENT_COUNT_GE: printf(">= "); break; + case IPT_RECENT_COUNT_GT: printf("> "); break; + default: printf(" "); + } + printf("%d ",info->entry_count); + if (info->count_ops & IPT_RECENT_TIME_OPS) switch (info->count_ops & IPT_RECENT_TIME_OPS) { + case IPT_RECENT_TIME_LT: printf("< "); break; + case IPT_RECENT_TIME_LE: printf("<= "); break; + case IPT_RECENT_TIME_GE: printf(">= "); break; + case IPT_RECENT_TIME_GT: printf("> "); break; + default: printf(" "); + } + printf("%d ",info->entry_time); + } +#endif + if (info->invert) fputc('!', stdout); - printf("recent: "); if(info->check_set & IPT_RECENT_SET) printf("SET "); if(info->check_set & IPT_RECENT_CHECK) printf("CHECK "); if(info->check_set & IPT_RECENT_UPDATE) printf("UPDATE "); @@ -203,6 +341,31 @@ { struct ipt_recent_info *info = (struct ipt_recent_info *)match->data; +#ifdef IPT_RECENT_HAS_LIST_OPS + /* handle the precondition first */ + if (info->count_ops) { + if (info->count_ops & IPT_RECENT_COUNT_INVERT) printf("! "); + switch (info->count_ops & IPT_RECENT_COUNT_OPS) { + case IPT_RECENT_COUNT_LT: printf("--listcount-lt "); break; + case IPT_RECENT_COUNT_LE: printf("--listcount-le "); break; + case IPT_RECENT_COUNT_EQ: printf("--listcount-eq "); break; + case IPT_RECENT_COUNT_GE: printf("--listcount-ge "); break; + case IPT_RECENT_COUNT_GT: printf("--listcount-gt "); break; + default: printf(" "); + } + printf("%d ",info->entry_count); + + if (info->count_ops & IPT_RECENT_TIME_OPS) switch (info->count_ops & IPT_RECENT_TIME_OPS) { + case IPT_RECENT_TIME_LT: printf("--listtime-lt "); break; + case IPT_RECENT_TIME_LE: printf("--listtime-le "); break; + case IPT_RECENT_TIME_GE: printf("--listtime-ge "); break; + case IPT_RECENT_TIME_GT: printf("--listtime-gt "); break; + default: printf(" "); + } + printf("%d ",info->entry_time); + } +#endif + if (info->invert) printf("! ");