Re: Ebtables NFQUEUE Support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I forgot the ebtables command patch, here it is..

diff -upNr old/extensions/ebt_nfqueue.c new/extensions/ebt_nfqueue.c
--- old/extensions/ebt_nfqueue.c    1970-01-01 08:00:00.000000000 +0800
+++ new/extensions/ebt_nfqueue.c    2012-10-24 14:35:40.000000000 +0800
@@ -0,0 +1,127 @@
+/*
+ * Shared library add-on to ebtables for NFQ
+ *
+ * (C) 2012 by Ma Jie Yue <jieyue.majy@xxxxxxxxxxxxxx>
+ *
+ * This program is distributed under the terms of GNU GPLv2, 1991
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <errno.h>
+
+#include "../include/ebtables_u.h"
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_bridge/ebt_nfqueue.h>
+
+#define NFQUEUE_QUEUENUM 0x1
+#define NFQUEUE_QUEUEBALANCE 0x2
+
+static int string_to_number(const char *s, unsigned int min, unsigned
int max, unsigned int *ret)
+{
+   long number;
+   char *end;
+   errno = 0;
+   number = strtol(s, &end, 0);
+
+   if (*end == '\0' && end != s) {
+       if (errno != ERANGE && min <= number && number <= max) {
+           *ret = number;
+           return 0;
+       }
+   }
+   return -1;
+}
+
+static void nfqueue_help(void)
+{
+   printf("NFQUEUE target options\n"
+           "  --queue-num value       Send packet to QUEUE number <value>.\n"
+           "                          Valid queue numbers are 0-65535\n");
+}
+
+static void nfqueue_init(struct ebt_entry_target* target) {
+   struct xt_NFQ_info* info = (struct xt_NFQ_info *)target->data;
+
+   info->queuenum = 0;
+}
+
+static const struct option nfqueue_opts[] = {
+   { "queue-num", 1, NULL, 'F' },
+   { "queue-balance", 1, NULL, 'B' },
+   { .name = NULL }
+};
+
+static void parse_num(const char *s, struct xt_NFQ_info *tinfo)
+{
+   unsigned int num = 0;
+   if (string_to_number(s, 0, 65535, &num) < 0) {
+       ebt_print_error("Invalid queue number %s\n", s);
+   }
+
+   tinfo->queuenum = num;
+}
+
+static int nfqueue_parse(int c, char **argv, int argc,
+       const struct ebt_u_entry *entry, unsigned int *flags,
+       struct ebt_entry_target **target)
+{
+   struct xt_NFQ_info *tinfo = (struct xt_NFQ_info *)(*target)->data;
+   tinfo->queuenum = 0;
+
+   switch (c) {
+       case 'F':
+           if (*flags)
+               ebt_print_error2("NFQUEUE target: "
+                               "Only use --queue-num ONCE!");
+           *flags |= NFQUEUE_QUEUENUM;
+           parse_num(optarg, tinfo);
+           break;
+
+       case 'B':
+           ebt_print_error2("NFQUEUE target: "
+                           "--queue-balance not supported (kernel too old?)");
+
+       default:
+           break;
+   }
+   return 1;
+}
+
+static void nfqueue_print(const struct ebt_u_entry* entry, const
struct ebt_entry_target *target) {
+   struct xt_NFQ_info *tinfo = (struct xt_NFQ_info *)target->data;
+
+   printf("--queue-num %u ", tinfo->queuenum);
+}
+
+static void nfqueue_check(const struct ebt_u_entry *entry,
+               const struct ebt_entry_target *target, const char *name,
+               unsigned int hookmask, unsigned int time) {
+
+}
+
+static int nfqueue_compare(const struct ebt_entry_target *t1, const
struct ebt_entry_target *t2) {
+   struct xt_NFQ_info *info1 = (struct xt_NFQ_info *)t1->data;
+   struct xt_NFQ_info *info2 = (struct xt_NFQ_info *)t2->data;
+
+   return (info1->queuenum == info2->queuenum);
+}
+
+static struct ebt_u_target nfqueue_target = {
+   .name       = "nfqueue",
+   .init       = nfqueue_init,
+   .size       = sizeof(struct xt_NFQ_info),
+   .help       = nfqueue_help,
+   .parse      = nfqueue_parse,
+   .print      = nfqueue_print,
+   .final_check    = nfqueue_check,
+   .compare    = nfqueue_compare,
+   .extra_ops  = nfqueue_opts,
+};
+
+void _init(void) {
+   ebt_register_target(&nfqueue_target);
+}
+
diff -upNr old/extensions/Makefile new/extensions/Makefile
--- old/extensions/Makefile 2011-12-16 04:02:47.000000000 +0800
+++ new/extensions/Makefile 2012-10-24 14:18:50.000000000 +0800
@@ -1,7 +1,7 @@
 #! /usr/bin/make

 EXT_FUNC+=802_3 nat arp arpreply ip ip6 standard log redirect vlan
mark_m mark \
-          pkttype stp among limit ulog nflog
+          pkttype stp among limit ulog nflog nfqueue
 EXT_TABLES+=filter nat broute
 EXT_OBJS+=$(foreach T,$(EXT_FUNC), extensions/ebt_$(T).o)
 EXT_OBJS+=$(foreach T,$(EXT_TABLES), extensions/ebtable_$(T).o)
diff -upNr old/include/linux/netfilter_bridge/ebt_nfqueue.h
new/include/linux/netfilter_bridge/ebt_nfqueue.h
--- old/include/linux/netfilter_bridge/ebt_nfqueue.h    1970-01-01
08:00:00.000000000 +0800
+++ new/include/linux/netfilter_bridge/ebt_nfqueue.h    2012-10-24
14:17:02.000000000 +0800
@@ -0,0 +1,11 @@
+#ifndef __LINUX_BRIDGE_EBT_NFQUEUE_H
+#define __LINUX_BRIDGE_EBT_NFQUEUE_H
+
+#include <linux/types.h>
+
+struct xt_NFQ_info {
+   __u16 queuenum;
+   int target;
+};
+
+#endif


On Wed, Oct 24, 2012 at 1:16 PM, JieYue Ma <xiaoma80.dev@xxxxxxxxx> wrote:
> Well, I wrote the nfqueue patch for both ebtables and arptables a few
> months ago, it did work well, so I think it is appropriate to release
> these patches. Hope it will help you.
>
> I am not sure if I understand the problem you raised correctly. I
> guess it might be the netfilter sus-subsystem currently not supporting
> queue verdict for bridge very well. As you can see, you need a
> nf_afinfo structure to be registered before using netfilter queue
> verdict for this protocol. Unfortunately, during initialization of
> netfilter, it did register such nf_afinfo for ipv4, ipv6, maybe arp as
> well.. but not for bridge. So in order to enable queue verdict to work
> under bridge, you need to register it by yourself, maybe during
> initialization of ebtables nfqueue target module
>
> here is my patch for ebtables:
>
>
> diff -upNr old/include/linux/netfilter_bridge/ebt_nfqueue.h
> new/include/linux/netfilter_bridge/ebt_nfqueue.h
> --- old/include/linux/netfilter_bridge/ebt_nfqueue.h    1969-12-31
> 19:00:00.000000000 -0500
> +++ new/include/linux/netfilter_bridge/ebt_nfqueue.h    2012-05-29
> 23:59:06.940194206 -0400
> @@ -0,0 +1,10 @@
> +#ifndef __LINUX_BRIDGE_EBT_NFQUEUE_H
> +#define __LINUX_BRIDGE_EBT_NFQUEUE_H
> +#include <linux/types.h>
> +
> +struct xt_NFQ_info {
> +        __u16 queuenum;
> +        int target;
> +};
> +
> +#endif
> diff -upNr old/net/bridge/netfilter/ebtables.c
> new/net/bridge/netfilter/ebtables.c
> --- old/net/bridge/netfilter/ebtables.c 2012-05-27 08:48:00.095617214 -0400
> +++ new/net/bridge/netfilter/ebtables.c 2012-05-27 08:57:27.644193954 -0400
> @@ -252,6 +252,17 @@ letsreturn:
>             return NF_DROP;
>         }
>  #endif
> +       /*
> +        * We add NFQUEUE support in ebtables here:
> +        *
> +        * If verdict is NF_QUEUE type, pass it to Netfilter. Netfilter will
> +        * call nf_queue to handle this.
> +        */
> +       if (verdict > 0 && (verdict & NF_VERDICT_MASK) == NF_QUEUE) {
> +           read_unlock_bh(&table->lock);
> +           return verdict;
> +       }
> +
>         /* jump to a udc */
>         cs[sp].n = i + 1;
>         cs[sp].chaininfo = chaininfo;
>
> diff -upNr old/net/bridge/netfilter/ebt_nfqueue.c
> new/net/bridge/netfilter/ebt_nfqueue.c
> --- old/net/bridge/netfilter/ebt_nfqueue.c  1969-12-31 19:00:00.000000000 -0500
> +++ new/net/bridge/netfilter/ebt_nfqueue.c  2012-05-27 08:58:58.511193378 -0400
> @@ -0,0 +1,117 @@
> +/*
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/skbuff.h>
> +#include <linux/kernel.h>
> +#include <linux/types.h>
> +#include <linux/netfilter.h>
> +#include <linux/netfilter/x_tables.h>
> +#include <linux/netfilter_bridge/ebtables.h>
> +#include <linux/netfilter_bridge/ebt_nfqueue.h>
> +
> +MODULE_AUTHOR("alibaba");
> +MODULE_DESCRIPTION("ebtables: forwarding to netlink");
> +MODULE_LICENSE("GPL");
> +
> +static unsigned int ebt_nfqueue_tg(struct sk_buff *skb, const struct
> xt_target_param *par) {
> +   const struct xt_NFQ_info *info = par->targinfo;
> +
> +   return NF_QUEUE_NR(info->queuenum);
> +}
> +
> +static bool ebt_nfqueue_tg_check(const struct xt_tgchk_param* par) {
> +   const struct xt_NFQ_info *info = par->targinfo;
> +
> +   if (BASE_CHAIN && info->target == EBT_RETURN) {
> +       printk(KERN_INFO"ebt_nfqueue: ebt_nfqueue_tg_check failed\n");
> +       return false;
> +   }
> +
> +   return true;
> +}
> +
> +void dummy_from_user(void *dst, void *src) {
> +}
> +
> +int dummy_to_user(void __user *dst, void *src) {
> +   return 0;
> +}
> +
> +static struct xt_target nfqueue_tg_reg __read_mostly = {
> +   .name           = "nfqueue",
> +   .revision   = 0,
> +   .family     = NFPROTO_BRIDGE,
> +   .table      = "filter",
> +   .hooks      = (1 << NF_BR_NUMHOOKS) | (1 << NF_BR_LOCAL_IN) | (1
> << NF_BR_LOCAL_OUT) | (1 << NF_BR_FORWARD),
> +        .target         = ebt_nfqueue_tg,
> +        .checkentry     = ebt_nfqueue_tg_check,
> +        .targetsize     = XT_ALIGN(sizeof(struct xt_NFQ_info)),
> +   .compat_from_user = dummy_from_user,
> +   .compat_to_user = dummy_to_user,
> +        .me             = THIS_MODULE,
> +};
> +
> +
> +__sum16 nf_br_checksum(struct sk_buff* skb, unsigned int hook,
> unsigned int dataoff, u_int8_t protocol) {
> +   return 0;
> +}
> +
> +static __sum16 nf_br_checksum_partial(struct sk_buff* skb, unsigned int hook,
> +       unsigned int dataoff, unsigned int len,
> +       u_int8_t protocol) {
> +   return 0;
> +}
> +
> +static int nf_br_route(struct dst_entry **dst, struct flowi *fl) {
> +   return 0;
> +}
> +
> +static void nf_br_saveroute(const struct sk_buff *skb, struct
> nf_queue_entry *entry) {
> +
> +}
> +
> +static int nf_br_reroute(struct sk_buff *skb, const struct
> nf_queue_entry *entry) {
> +   return 0;
> +}
> +
> +static const struct nf_afinfo nf_br_afinfo = {
> +   .family     = NFPROTO_BRIDGE,
> +   .checksum   = nf_br_checksum,
> +   .checksum_partial = nf_br_checksum_partial,
> +   .route      = nf_br_route,
> +   .saveroute  = nf_br_saveroute,
> +   .reroute    = nf_br_reroute,
> +   .route_key_size = 0,
> +};
> +
> +
> +static int __init nfqueue_tg_init(void)
> +{
> +   int ret;
> +   /*
> +    * a tricky hack here, we forge a bridge nf_afinfo struct and register it
> +    *
> +    * We have to do this, coz currently netfilter subsystem doesn't
> support bridge in nf_queue
> +    */
> +   ret = nf_register_afinfo(&nf_br_afinfo);
> +   if (ret < 0) {
> +       printk("[ebt_nfqueue] nf_register_afinfo failed, cannot
> install ebt_nfqueue.ko\n");
> +       return ret;
> +   }
> +
> +   return xt_register_target(&nfqueue_tg_reg);
> +}
> +
> +static void __exit nfqueue_tg_exit(void)
> +{
> +   nf_unregister_afinfo(&nf_br_afinfo);
> +   xt_unregister_target(&nfqueue_tg_reg);
> +}
> +
> +module_init(nfqueue_tg_init);
> +module_exit(nfqueue_tg_exit);
>
>
>
>
> On Sat, Oct 20, 2012 at 2:32 AM, Benjamin Beckmeyer
> <B.Beckmeyer@xxxxxxxxxxxxxxxxxxxx> wrote:
>> Hi all,
>>
>> I am trying to build an Ebtables NFQUEUE module to also move layer 2
>> traffic to the NFQUEUE system provided by IPtables.  A few years ago a
>> Pierre Chifflier provided 3 patches to Ebtables that appear to try and
>> utilize the NFQUEUE xt_tables target within Ebtables to pass the layer 2
>> data via nfnetlink_queue.
>>
>> Some background, I am trying to get this working on 2.6.26.5 kernel
>> version and have applied the patches listed here:
>>
>> http://permalink.gmane.org/gmane.comp.security.firewalls.netfilter.devel/37859
>> http://permalink.gmane.org/gmane.comp.security.firewalls.netfilter.devel/37862
>>
>> I have also patched the Ebtables (2.0.8) userspace utility to produce the
>> shared object ebt_NFQUEUE.so with code also from Pierre, which can be
>> found here:
>>
>> https://www.wzdftpd.net/downloads/ebt_NFQUEUE.c
>>
>> To get the patches to work for the ebt_nfqueue kernel object, due to an
>> older kernel, I had to modify the target and check function arguments as
>> the "const struct xt_action_param" does not exist in my kernel version:
>>
>> static int ebt_nfqueue_tg(const struct sk_buff *skb, const struct
>> net_device *in,
>>                                    const struct net_device *out, const void *data, unsigned int datalen)
>> {
>>     const struct ebt_nfqueue_info *info = data;
>>     struct nf_loginfo li;
>>     unsigned int verdict = NF_ACCEPT;
>>
>>     printk(KERN_NOTICE "ebt_NFQUEUE: returning EBT_QUEUE\n");
>>     return EBT_QUEUE; // return -5
>> }
>>
>> static struct ebt_target ebt_nfqueue __read_mostly = {
>>     .name               = "NFQUEUE",
>>     .target     = ebt_nfqueue_tg,
>>     .check = ebt_nfqueue_check,
>>     .me                 = THIS_MODULE,
>> };
>>
>> +++++ VERSUS +++++
>>
>> static struct xt_target ebt_xt_nfqueue __read_mostly = {
>>     .name               = "NFQUEUE",
>>     .revision   = 0,
>>     .family     = 7, // NFPROTO_BRIDGE
>>     .target     = ebt_nfqueue_tg,
>>     .checkentry = ebt_nfqueue_check,
>>     .targetsize = sizeof(struct ebt_nfqueue_info),
>>     .me                 = THIS_MODULE,
>> };
>>
>> Nevertheless, the return value from this target is just the EBT_QUEUE (-5)
>> to inform the Netfilter system of the queue number.  If I use the
>> ebt_target rather than xt_target the kernel module will build and can be
>> inserted into ebtables with no errors - the problem is that queuing does
>> not work.  If I use the xt_target rather than the ebt_target then Ebtables
>> userspace complains that it is not supported from this kernel version
>> (error in communication.c in userspace and appears to fail on the
>> "setsockopt" calls).
>>
>> I have printed out the entire contents of using the xt_target vs
>> ebt_target and all data going into this call is identical, which boggles
>> my mind as to why xt_target will trigger the error in the ebtables
>> userspace program and ebt_target will not.
>>
>> I think that I MUST use the xt_target within ebtables to properly pass
>> this data to the NFQUEUE system.  This comes from an earlier discussion:
>>
>> +++
>>
>> On 04.02.2011 14:40, Pierre Chifflier wrote:
>>> On 02/04/2011 02:25 PM, Patrick McHardy wrote:
>>>> On 03.02.2011 15:32, Pierre Chifflier wrote:
>>>>> This adds support for sending bridge packets to userspace using
>>>>> the NFQUEUE target with ebtables.
>>>>
>>>> I don't think we need a new target for this (and the EBT_QUEUE
>>>> definition), just using xt_NFQUEUE should work fine.
>>>
>>> I thought ebtables did not support sending packet to xtables ? (that's
>>> on the TODO list for ebtables).
>>
>> It can use xtables targets and matches if I'm not completely
>> mistaken.
>>
>> +++
>>
>> It appears I can 'use' xtables targets, it will compile correctly, but
>> ebtables will not actually allow me to insert the rules to jump to the
>> NFQUEUE target, so I am unable to actually verify if packets would be
>> queue'd by the system.
>>
>> When using the ebt_target I can insert my NFQUEUE rules into the nat
>> PREROUTING table, and the packet counter will actually increment on layer
>> 2 traffic, but the packets do not appear to actually hit any of the
>> nfnetlink_queue functions (I have added a printk to every function). I
>> even see that my target has been hit via a printk:
>>
>> user.notice kernel: ebt_NFQUEUE: returning EBT_QUEUE
>>
>> But then it appears that is as far as the packet goes.
>>
>> When queueing a packet from IPtables I see a huge amount of output:
>>
>> user.notice kernel: BB: File: nfnetlink_queue.c        Function:
>> __enqueue_entry
>> user.notice kernel: BB: File: nfnetlink.c      Function: nfnetlink_rcv
>> user.notice kernel: BB: File: nfnetlink.c      Function: nfnl_lock
>> user.notice kernel: BB: File: nfnetlink.c      Function: nfnetlink_rcv_msg
>> user.notice kernel: BB: File: nfnetlink.c      Function: nfnetlink_get_subsys
>> user.notice kernel: BB: File: nfnetlink.c      Function:
>> nfnetlink_find_client
>> user.notice kernel: BB: File: nfnetlink_queue.c        Function:
>> nfqnl_recv_verdict
>> user.notice kernel: BB: File: nfnetlink_queue.c        Function:
>> instance_lookup
>> user.notice kernel: BB: File: nfnetlink_queue.c        Function:
>> find_dequeue_entry
>> user.notice kernel: BB: File: nfnetlink.c      Function: nfnl_unlock
>> user.notice kernel: BB: File: nfnetlink_queue.c        Function:
>> nfqnl_enqueue_packet
>> user.notice kernel: BB: File: nfnetlink_queue.c        Function:
>> instance_lookup
>> user.notice kernel: BB: File: nfnetlink_queue.c        Function:
>> nfqnl_build_packet_message
>> user.notice kernel: BB: File: nfnetlink.c      Function: nfnetlink_unicast
>>
>> But from my ebtables -j NFQUEUE there are no calls to the nfnetlink.c or
>> nfnetlink_queue.c functions.  It is almost like the target is hit then the
>> packet is just mysteriously gone...or hits other functions unrelated to
>> the queueing system.
>>
>> In summation, the problem is if using the ebt_target struct in the kernel
>> module for ebtables, it will be inserted and can be utilized by the
>> userspace Ebtables - but it doesnt appear to pass the packet to the
>> IPtables nfqueue correctly.  If using the xt_target struct in the kernel
>> module for ebtables, it will compile, but fails to be utilized by Ebtables
>> userspace due to a "setsockopt error mentioned above.
>>
>> Any help or suggestions are greatly appreciated!
>>
>> Thank you, Benny
>>
>>
>>
>>
>>
>>
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe netfilter" in
>> the body of a message to majordomo@xxxxxxxxxxxxxxx
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe netfilter" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Netfilter Development]     [Linux Kernel Networking Development]     [Netem]     [Berkeley Packet Filter]     [Linux Kernel Development]     [Advanced Routing & Traffice Control]     [Bugtraq]

  Powered by Linux