Eu encontrei o mesmo problema e atualizei o módulo u32. Eu tenho dois patches para o kernel 2.6.30, um para o kernel e outro para o usuário. Eles provavelmente não lidarão com cargas úteis fragmentadas melhor do que o correspondente do u32 original, mas funcionou para o meu problema.
Patch de kernel:
diff -ruNd linux-2.6.30.4patch/net/netfilter/xt_u32.c linux-2.6.30/net/netfilter/xt_u32.c
--- linux-2.6.30.4patch/net/netfilter/xt_u32.c 2014-03-19 13:24:06.000000000 +0100
+++ linux-2.6.30/net/netfilter/xt_u32.c 2014-10-02 13:12:33.244444192 +0200
@@ -13,9 +13,13 @@
#include <linux/types.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_u32.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+
static bool u32_match_it(const struct xt_u32 *data,
- const struct sk_buff *skb)
+ const struct sk_buff *skb,
+ unsigned int PayloadOffset)
{
const struct xt_u32_test *ct;
unsigned int testind;
@@ -34,7 +38,7 @@
for (testind = 0; testind < data->ntests; ++testind) {
ct = &data->tests[testind];
at = 0;
- pos = ct->location[0].number;
+ pos = PayloadOffset + ct->location[0].number;
if (skb->len < 4 || pos > skb->len - 4)
return false;
@@ -92,27 +96,91 @@
const struct xt_u32 *data = par->matchinfo;
bool ret;
- ret = u32_match_it(data, skb);
+ ret = u32_match_it(data, skb, 0);
return ret ^ data->invert;
}
-static struct xt_match xt_u32_mt_reg __read_mostly = {
- .name = "u32",
- .revision = 0,
- .family = NFPROTO_UNSPEC,
- .match = u32_mt,
- .matchsize = sizeof(struct xt_u32),
- .me = THIS_MODULE,
+static bool u32_tcp_mt(const struct sk_buff *skb, const struct xt_match_param *par)
+{
+ const struct xt_u32 *data = par->matchinfo;
+ const struct tcphdr *th;
+ struct tcphdr _tcph;
+ bool ret;
+
+ th = skb_header_pointer(skb, par->thoff, sizeof(_tcph), &_tcph);
+ if (th == NULL)
+ return false;
+
+ if (th->doff*4 < sizeof(*th))
+ return false;
+
+ /* printk("TCP payload match @%d\n", par->thoff + 4*th->doff); */
+ ret = u32_match_it(data, skb, par->thoff + 4*th->doff);
+ return ret ^ data->invert;
+}
+
+static bool u32_udp_mt(const struct sk_buff *skb, const struct xt_match_param *par)
+{
+ const struct xt_u32 *data = par->matchinfo;
+ bool ret;
+
+ /* printk("UDP payload match @%d\n", par->thoff + sizeof(struct udphdr) ); */
+ ret = u32_match_it(data, skb, par->thoff + sizeof(struct udphdr) );
+ return ret ^ data->invert;
+}
+
+static struct xt_match xt_u32_mt_reg[] __read_mostly = {
+ {
+ .name = "u32",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .match = u32_mt,
+ .matchsize = sizeof(struct xt_u32),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "payload",
+ .family = NFPROTO_IPV4,
+ .match = u32_tcp_mt,
+ .matchsize = sizeof(struct xt_u32),
+ .proto = IPPROTO_TCP,
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "payload",
+ .family = NFPROTO_IPV6,
+ .match = u32_tcp_mt,
+ .matchsize = sizeof(struct xt_u32),
+ .proto = IPPROTO_TCP,
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "payload",
+ .family = NFPROTO_IPV4,
+ .match = u32_udp_mt,
+ .matchsize = sizeof(struct xt_u32),
+ .proto = IPPROTO_UDP,
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "payload",
+ .family = NFPROTO_IPV6,
+ .match = u32_udp_mt,
+ .matchsize = sizeof(struct xt_u32),
+ .proto = IPPROTO_UDP,
+ .me = THIS_MODULE,
+ },
+
};
static int __init u32_mt_init(void)
{
- return xt_register_match(&xt_u32_mt_reg);
+ return xt_register_matches(xt_u32_mt_reg, ARRAY_SIZE(xt_u32_mt_reg));
}
static void __exit u32_mt_exit(void)
{
- xt_unregister_match(&xt_u32_mt_reg);
+ xt_unregister_matches(xt_u32_mt_reg, ARRAY_SIZE(xt_u32_mt_reg));
}
module_init(u32_mt_init);
@@ -122,3 +190,5 @@
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_u32");
MODULE_ALIAS("ip6t_u32");
+MODULE_ALIAS("ipt_payload");
+MODULE_ALIAS("ip6t_payload");
Patch de terreno do usuário:
diff -ruNd iptables-1.4.12.1.4patch/extensions/GNUmakefile.in iptables-1.4.12.1/extensions/GNUmakefile.in
--- iptables-1.4.12.1.4patch/extensions/GNUmakefile.in 2014-10-02 14:43:19.000000000 +0200
+++ iptables-1.4.12.1/extensions/GNUmakefile.in 2014-10-02 14:29:54.000000000 +0200
@@ -73,6 +73,7 @@
install: ${targets_install}
@mkdir -p "${DESTDIR}${xtlibdir}";
if test -n "${targets_install}"; then install -pm0755 $^ "${DESTDIR}${xtlibdir}/"; fi;
+ test -f "${DESTDIR}${xtlibdir}/libxt_u32.so" && ln -s "${DESTDIR}${xtlibdir}/libxt_u32.so" "${DESTDIR}${xtlibdir}/libxt_payload.so"
clean:
rm -f *.o *.oo *.so *.a {matches,targets}[46].man initext.c initext4.c initext6.c;
diff -ruNd iptables-1.4.12.1.4patch/extensions/libxt_u32.c iptables-1.4.12.1/extensions/libxt_u32.c
--- iptables-1.4.12.1.4patch/extensions/libxt_u32.c 2014-10-02 14:43:19.000000000 +0200
+++ iptables-1.4.12.1/extensions/libxt_u32.c 2014-10-02 13:57:24.000000000 +0200
@@ -31,7 +31,7 @@
static void u32_help(void)
{
printf(
- "u32 match options:\n"
+ "u32/payload match options:\n"
"[!] --u32 tests\n"
"\t\t""tests := location \"=\" value | tests \"&&\" location \"=\" value\n"
"\t\t""value := range | value \",\" range\n"
@@ -249,7 +249,7 @@
int numeric)
{
const struct xt_u32 *data = (const void *)match->data;
- printf(" u32");
+ printf(" %s", match->u.user.name);
if (data->invert)
printf(" !");
u32_dump(data);
@@ -277,7 +277,21 @@
.x6_options = u32_opts,
};
+static struct xtables_match payload_match = {
+ .name = "payload",
+ .family = NFPROTO_UNSPEC,
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_u32)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_u32)),
+ .help = u32_help,
+ .print = u32_print,
+ .save = u32_save,
+ .x6_parse = u32_parse,
+ .x6_options = u32_opts,
+};
+
void _init(void)
{
xtables_register_match(&u32_match);
+ xtables_register_match(&payload_match);
}