Ключевые слова:ipfw, firewall, freebsd, limit, traffic, patch, (найти похожие документы)
From: Andrey V. Elsukov <bu7cher@yandex.ru.>
Newsgroups: email
Date: Mon, 06 May 2005 14:31:37 +0000 (UTC)
Subject: Патч для ipfw, правила срабатывающих в зависимости от объема трафика
Патч для ipfw, позволяющий задавать правила срабатыванющие в зависимость
от объема трафика прошедшего в соответвсии с дпределенным правилом
Патч небольшой, и при желании его функциональность может быть легко
расширена. На данный момент патч делает следующие изменения в системе:
*** в IPFW добавляется новая опция (см. man ipfw: RULE OPTIONS/MATCH
PATTERNS) bound числовое_значение. Правила с этой опцией проходят
дополнительную проверку. Проверка заключается в сравнении байтового
счётчика правила со значением указанном в bound. Если значение счётчика
меньше значения в bound, то правило срабатывает (конечно при этом
делаются все остальные проверки), иначе - пропускается.
*** необходимые для поддержки выше описанного изменения в утилите
/sbin/ipfw.
Зачем все это?
Приведу простой пример:
ipfw add 100 allow ip from any to hostA in recv internet bound 10000000
ipfw add 200 deny ip from any to any
Здесь hostA - это хост, у которого лимит входящего траффика ~10 MБайт.
Сотое правило перестанет срабатывать когда лимит будет исчерпан. Можно
придумать и более сложные конструкции.
Как установить?
Патч писался для FreeBSD 5.4-STABLE, т.е. RELENG_5. Исходя из этого
ставим так:
1. Патчим:
# cd /usr/src
# patch < путь/к/патчу
2. Чтобы утилиту ipfw можно было скомпилить, нужно заменить один
заголовочный файл:
# cp /usr/src/sys/netinet/ip_fw.h /usr/include/netinet/
3. В зависимости от того как у вас сконфигурирована система, нужно
перекомпилировать и установить либо модуль ядра ipfw.ko, либо само ядро.
Так же утилиту ipfw.
# cd /usr/src/sys/modules/ipfw/ && make depend all install
# cd /usr/src/sbin/ipfw/ && make depend all install
Текст патча:
--- sys/netinet/ip_fw.h.orig Tue Feb 1 02:26:35 2005
+++ sys/netinet/ip_fw.h Tue May 3 22:38:07 2005
@@ -78,6 +78,7 @@
O_RECV, /* none */
O_XMIT, /* none */
O_VIA, /* none */
+ O_BOUND, /* u64 = bound in bytes */
O_IPOPT, /* arg1 = 2*u8 bitmap */
O_IPLEN, /* arg1 = len */
@@ -198,6 +199,14 @@
ipfw_insn o;
u_int32_t d[1]; /* one or more */
} ipfw_insn_u32;
+
+/*
+ * This is used to store 64-bit bound value.
+ */
+typedef struct _ipfw_insn_u64 {
+ ipfw_insn o;
+ u_int64_t bound;
+} ipfw_insn_u64;
/*
* This is used to store IP addr-mask pairs.
--- sys/netinet/ip_fw2.c.orig Sun Feb 6 19:16:20 2005
+++ sys/netinet/ip_fw2.c Tue May 3 22:22:04 2005
@@ -2294,6 +2294,9 @@
/* otherwise no match */
break;
+ case O_BOUND:
+ match = (f->bcnt < ((ipfw_insn_u64 *)cmd)->bound);
+ break;
/*
* The second set of opcodes represents 'actions',
* i.e. the terminal part of a rule once the packet
@@ -2939,6 +2942,11 @@
if (cmdlen != F_INSN_SIZE(ipfw_insn_u32))
goto bad_size;
break;
+
+ case O_BOUND:
+ if (cmdlen != F_INSN_SIZE(ipfw_insn_u64))
+ goto bad_size;
+ break;
case O_LIMIT:
if (cmdlen != F_INSN_SIZE(ipfw_insn_limit))
--- sbin/ipfw/ipfw2.c.orig Tue Jan 25 10:23:34 2005
+++ sbin/ipfw/ipfw2.c Tue May 3 22:56:41 2005
@@ -236,6 +236,7 @@
TOK_ANTISPOOF,
TOK_IPSEC,
TOK_COMMENT,
+ TOK_BOUND,
TOK_PLR,
TOK_NOERROR,
@@ -351,6 +352,7 @@
{ "antispoof", TOK_ANTISPOOF },
{ "ipsec", TOK_IPSEC },
{ "//", TOK_COMMENT },
+ { "bound", TOK_BOUND },
{ "not", TOK_NOT }, /* pseudo option */
{ "!", /* escape ? */ TOK_NOT }, /* pseudo option */
@@ -1198,6 +1200,9 @@
break;
}
+ case O_BOUND:
+ printf(" bound %u", ((ipfw_insn_u64 *)cmd)->bound);
+ break;
case O_IPID:
if (F_LEN(cmd) == 1)
printf(" ipid %u", cmd->arg1 );
@@ -1917,7 +1922,7 @@
" ipttl LIST | ipversion VER | keep-state | layer2 | limit ... |\n"
" mac ... | mac-type LIST | proto LIST | {recv|xmit|via} {IF|IPADDR} |\n"
" setup | {tcpack|tcpseq|tcpwin} NN | tcpflags SPEC | tcpoptions SPEC |\n"
-" verrevpath | versrcreach | antispoof\n"
+" bound VALUE | verrevpath | versrcreach | antispoof\n"
);
exit(0);
}
@@ -3220,6 +3225,14 @@
cmd->opcode = O_RECV;
else if (i == TOK_VIA)
cmd->opcode = O_VIA;
+ break;
+
+ case TOK_BOUND:
+ NEED1("bound requires numeric value");
+ cmd->opcode = O_BOUND;
+ ((ipfw_insn_u64 *)cmd)->bound = strtoull(*av, NULL, 0);
+ cmd->len |= F_INSN_SIZE(ipfw_insn_u64);
+ ac--; av++;
break;
case TOK_ICMPTYPES:
--- sbin/ipfw/ipfw.8.orig Wed Mar 2 22:50:11 2005
+++ sbin/ipfw/ipfw.8 Wed May 4 19:23:13 2005
@@ -920,6 +920,8 @@
.It Cm bridged
Alias for
.Cm layer2 .
+.It Cm bound Ar value
+Matches while bytes counter below bound value.
.It Cm dst-ip Ar ip-address
Matches IP packets whose destination IP is one of the address(es)
specified as argument.