netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* new target - ebtables dynamic snat, kernel and userspace patch
@ 2009-09-24  7:43 Shai Tahar
  2009-09-24  8:12 ` Jan Engelhardt
  2009-09-24 20:24 ` Bart De Schuymer
  0 siblings, 2 replies; 6+ messages in thread
From: Shai Tahar @ 2009-09-24  7:43 UTC (permalink / raw)
  To: netfilter-devel; +Cc: bdschuym, shai.tahar

---- README ---
ebt_dyn_snat - ebtable dynamic snat
     Authors:
       Shai Tahar <shai.tahar@storwize.com>

     Changes source mac address according to source ip address based on 
local arp table
     to be used when source ip address is snated

Copyright (C) 2009 Storwize

ebtables target for transparent bridge
[user]<--->[transparent bridge]<--->[server]

if the transparent bridge maskes user ip address towards the server,
the bridge normally would replace the source mac address with the bridge 
mac
till now, using arptables and ebtables snat and arpreply targets used 
for overcoming this scenario.

using the attached target will rewrite the packet source mac address 
based on local arp table
(no need for arptables and arpreplay)

1. new ebtables target: dynamic snat target support
       depends on BRIDGE_NF_EBTABLES
       This option adds the MAC DYN SNAT target, which allows altering 
dynamicly the MAC
       source address of frames based on local arp table.

2. ebtables userspace extension

use the following rules for a bridge (eth0,eth2)
ebtables -t nat -A POSTROUTING -p IPV4 -o eth0 -j dyn_snat 
--dyn-snat-target ACCEPT
ebtables -t nat -A POSTROUTING -p IPV4 -o eth2 -j dyn_snat 
--dyn-snat-target ACCEPT


---- kernel 2.6.26 -- 2.6.30 ----

diff --git a/include/linux/netfilter_bridge/ebt_dyn_snat.h 
b/include/linux/netfilter_bridge/ebt_dyn_snat.h
new file mode 100644
index 0000000..b38b73b
--- /dev/null
+++ b/include/linux/netfilter_bridge/ebt_dyn_snat.h
@@ -0,0 +1,19 @@
+/*
+ *  ebtables dynamic snat
+ *
+ *      Authors:
+ *       Shai Tahar                <shai.tahar@storwize.com>
+ *
+ *  Copyright (C) 2009 Storwize
+ */
+#ifndef __LINUX_BRIDGE_EBT_DYN_SNAT_H
+#define __LINUX_BRIDGE_EBT_DYN_SNAT_H
+
+
+struct ebt_dyn_snat_info
+{
+       int           target;
+};
+#define EBT_DYN_SNAT_TARGET "dyn_snat"
+
+#endif
diff --git a/net/bridge/netfilter/ebt_dyn_snat.c 
b/net/bridge/netfilter/ebt_dyn_snat.c
new file mode 100644
index 0000000..9690c5e
--- /dev/null
+++ b/net/bridge/netfilter/ebt_dyn_snat.c
@@ -0,0 +1,111 @@
+/*
+ *  ebt_dyn_snat - ebtable dynamic snat
+ *
+ *     Authors:
+ *     Shai Tahar <shai.tahar@storwize.com>
+ *
+ *     changes source mac address according to source ip address based 
on local arp table
+ *     to be used when source ip address is snated
+ *
+ *  Copyright (C) 2009 Storwize
+ */
+
+
+#include <linux/netfilter.h>
+#include <linux/netfilter_bridge/ebtables.h>
+#include <linux/netfilter_bridge/ebt_dyn_snat.h>
+#include <linux/module.h>
+#include <net/sock.h>
+#include <linux/if_arp.h>
+#include <net/arp.h>
+#include "../br_private.h"
+#include <linux/ip.h>
+#include <net/ip.h>
+
+
+
+static struct net_device *bridge_parent(const struct net_device *dev)
+{
+        struct net_bridge_port *port = rcu_dereference(dev->br_port);
+        return port ? port->br->dev : NULL;
+}
+
+
+static int ebt_target_dyn_snat(struct sk_buff *skb, unsigned int hooknr,
+   const struct net_device *in, const struct net_device *out,
+   const void *data, unsigned int datalen)
+{
+       const struct ebt_dyn_snat_info *info = data;
+        const struct iphdr *ih;
+        struct iphdr _iph;
+       unsigned char mac[ETH_ALEN];
+
+        struct net_device *parent ;
+        __be32 ip;
+        struct neighbour *neigh;
+
+        if (!skb_make_writable(skb, 0))
+                return EBT_DROP;
+
+
+        ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
+        if (ih == NULL) return EBT_DROP;
+
+        parent = bridge_parent(out);
+
+        if (parent) {
+          ip = ih->saddr;
+          neigh = neigh_lookup(&arp_tbl,&ip, parent);
+          if (neigh) {
+                read_lock_bh(&neigh->lock);
+                memcpy(mac, neigh->ha, out->addr_len);
+                read_unlock_bh(&neigh->lock);
+                neigh_release(neigh);
+                memcpy(eth_hdr(skb)->h_source,mac, ETH_ALEN);
+          }
+        }
+       return info->target | ~EBT_VERDICT_BITS;
+}
+
+static int ebt_target_dyn_snat_check(const char *tablename, unsigned 
int hookmask,
+   const struct ebt_entry *e, void *data, unsigned int datalen)
+{
+       const struct ebt_dyn_snat_info *info = data;
+       int tmp;
+
+       if (datalen != EBT_ALIGN(sizeof(struct ebt_dyn_snat_info)))
+               return -EINVAL;
+       tmp = info->target | ~EBT_VERDICT_BITS;
+       if (BASE_CHAIN && tmp == EBT_RETURN)
+               return -EINVAL;
+       CLEAR_BASE_CHAIN_BIT;
+       if (strcmp(tablename, "nat"))
+               return -EINVAL;
+       if (hookmask & ~(1 << NF_BR_POST_ROUTING))
+               return -EINVAL;
+       if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
+               return -EINVAL;
+       return 0;
+}
+
+static struct ebt_target dyn_snat __read_mostly = {
+       .name           = EBT_DYN_SNAT_TARGET,
+       .target         = ebt_target_dyn_snat,
+       .check          = ebt_target_dyn_snat_check,
+       .me             = THIS_MODULE,
+};
+
+static int __init ebt_dyn_snat_init(void)
+{
+       return ebt_register_target(&dyn_snat);
+}
+
+static void __exit ebt_dyn_snat_fini(void)
+{
+       ebt_unregister_target(&dyn_snat);
+}
+
+module_init(ebt_dyn_snat_init);
+module_exit(ebt_dyn_snat_fini);
+MODULE_DESCRIPTION("Ebtables: Dynamic Source MAC address translation");
+MODULE_LICENSE("GPL");

----- user space based on ebtables 2.0.6  -----
diff --git a/ebtables-2.0.6/extensions/Makefile 
b/ebtables-2.0.6/extensions/Makefile
index 2361a4c..9f14627 100644
--- a/ebtables-2.0.6/extensions/Makefile
+++ b/ebtables-2.0.6/extensions/Makefile
@@ -1,6 +1,6 @@
 #! /usr/bin/make
 
-EXT_FUNC+=802_3 nat arp arpreply ip standard log redirect vlan mark_m 
mark \
+EXT_FUNC+=802_3 dyn_snat nat arp arpreply ip standard log redirect vlan 
mark_m mark \
           pkttype stp among limit
 EXT_TABLES+=filter nat broute
 EXT_OBJS+=$(foreach T,$(EXT_FUNC), extensions/ebt_$(T).o)

diff --git a/ebtables-2.0.6/extensions/ebt_dyn_snat.c 
b/ebtables-2.0.6/extensions/ebt_dyn_snat.c
new file mode 100644
index 0000000..38af510
--- /dev/null
+++ b/ebtables-2.0.6/extensions/ebt_dyn_snat.c
@@ -0,0 +1,126 @@
+/*
+ *  ebt_dyn_snat - ebtable dynamic snat
+ *
+ *      Authors:
+ *      Shai Tahar <shai.tahar@storwize.com>
+ *
+ *      changes source mac address according to source ip address based 
on local arp table
+ *      to be used when source ip address is snated
+ *
+ *  Copyright (C) 2009 Storwize
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/ether.h>
+#include <getopt.h>
+#include "../include/ebtables_u.h"
+#include <linux/netfilter_bridge/ebt_dyn_snat.h>
+
+
+#define DYN_SNAT_TARGET '1'
+static struct option opts[] =
+{
+    { "dyn-snat-target" , required_argument, 0, DYN_SNAT_TARGET },
+    { 0 }
+};
+
+static void print_help()
+{
+    printf(
+    "dynamic snat target options:\n"
+    " --dyn-snat-target target       : ACCEPT, DROP, RETURN or CONTINUE\n"
+    "                                   (standard target is DROP)\n" );
+}
+
+static void init(struct ebt_entry_target *target)
+{
+    struct ebt_dyn_snat_info *info =
+       (struct ebt_dyn_snat_info *)target->data;
+    info->target = EBT_DROP;
+}
+
+#define OPT_DYN_SNAT_TARGET   0x01
+
+static int parse(int c, char **argv, int argc,
+   const struct ebt_u_entry *entry, unsigned int *flags,
+   struct ebt_entry_target **target)
+{
+    struct ebt_dyn_snat_info *info =
+       (struct ebt_dyn_snat_info *)(*target)->data;
+    char *end;
+   
+
+    switch (c) {
+    case DYN_SNAT_TARGET:
+        check_option(flags, OPT_DYN_SNAT_TARGET);
+        if (FILL_TARGET(optarg, info->target))
+            print_error("Illegal --dyn-snat-target target");
+        break;
+
+    default:
+        return 0;
+    }
+    return 1;
+}
+
+static void final_check(const struct ebt_u_entry *entry,
+   const struct ebt_entry_target *target, const char *name,
+   unsigned int hookmask, unsigned int time)
+{
+    struct ebt_dyn_snat_info *info =
+       (struct ebt_dyn_snat_info *)target->data;
+
+    if (entry->ethproto != ETH_P_IP || entry->invflags & EBT_IPROTO)
+        print_error("For dynamic snat the protocol must be "
+                    "specified as IPV4");
+
+    if (BASE_CHAIN && info->target == EBT_RETURN)
+        print_error("--dyn-snat-target RETURN not allowed on "
+                    "base chain");
+
+    CLEAR_BASE_CHAIN_BIT;
+    if (strcmp(name, "nat") || hookmask & ~(1 << NF_BR_POST_ROUTING))
+        print_error("dynamic snat only allowed in POSTROUTING");
+}
+
+static void print(const struct ebt_u_entry *entry,
+   const struct ebt_entry_target *target)
+{
+    struct ebt_dyn_snat_info *info =
+       (struct ebt_dyn_snat_info *)target->data;
+
+    printf(" --dyn-snat-target %s", TARGET_NAME(info->target));
+}
+
+static int compare(const struct ebt_entry_target *t1,
+   const struct ebt_entry_target *t2)
+{
+    struct ebt_dyn_snat_info *info1 =
+       (struct ebt_dyn_snat_info *)t1->data;
+
+    struct ebt_dyn_snat_info *info2 =
+       (struct ebt_dyn_snat_info *)t2->data;
+
+    return info1->target == info2->target;
+}
+
+static struct ebt_u_target dyn_snat_target =
+{
+    .name        = EBT_DYN_SNAT_TARGET,
+    .size        = sizeof(struct ebt_dyn_snat_info),
+    .help        = print_help,
+    .init        = init,
+    .parse        = parse,
+    .final_check    = final_check,
+    .print        = print,
+    .compare    = compare,
+    .extra_ops    = opts,
+};
+
+static void _init(void) __attribute__ ((constructor));
+static void _init(void)
+{
+    register_target(&dyn_snat_target);
+}
diff --git 
a/ebtables-2.0.6/include/linux/netfilter_bridge/ebt_dyn_snat.h 
b/ebtables-2.0.6/include/linux/netfilter_bridge/ebt_dyn_snat.h
new file mode 100644
index 0000000..8abb0cb
--- /dev/null
+++ b/ebtables-2.0.6/include/linux/netfilter_bridge/ebt_dyn_snat.h
@@ -0,0 +1,23 @@
+/*
+ *  ebt_dyn_snat - ebtable dynamic snat
+ *
+ *      Authors:
+ *      Shai Tahar <shai.tahar@storwize.com>
+ *
+ *      changes source mac address according to source ip address based 
on local arp table
+ *      to be used when source ip address is snated
+ *
+ *  Copyright (C) 2009 Storwize
+ */
+
+#ifndef __LINUX_BRIDGE_EBT_DYN_SNAT_H
+#define __LINUX_BRIDGE_EBT_DYN_SNAT_H
+
+
+struct ebt_dyn_snat_info
+{
+    int           target;
+};
+#define EBT_DYN_SNAT_TARGET "dyn_snat"
+
+#endif

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: new target - ebtables dynamic snat, kernel and userspace patch
  2009-09-24  7:43 new target - ebtables dynamic snat, kernel and userspace patch Shai Tahar
@ 2009-09-24  8:12 ` Jan Engelhardt
  2009-09-24  8:30   ` Shai Tahar
  2009-09-24 20:24 ` Bart De Schuymer
  1 sibling, 1 reply; 6+ messages in thread
From: Jan Engelhardt @ 2009-09-24  8:12 UTC (permalink / raw)
  To: Shai Tahar; +Cc: netfilter-devel, bdschuym, shai.tahar


On Thursday 2009-09-24 09:43, Shai Tahar wrote:

> ---- README ---
> ebt_dyn_snat - ebtable dynamic snat
>    Authors:
>      Shai Tahar <shai.tahar@storwize.com>
>
>    Changes source mac address according to source ip address based on local
> arp table
>    to be used when source ip address is snated
>
> Copyright (C) 2009 Storwize
>
> ebtables target for transparent bridge
> [user]<--->[transparent bridge]<--->[server]
>
> if the transparent bridge maskes user ip address towards the server,
> the bridge normally would replace the source mac address

Well, if you want to have the client's original MAC address in the
packet, do not SNAT it. It (seems) as simple as that.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: new target - ebtables dynamic snat, kernel and userspace patch
  2009-09-24  8:12 ` Jan Engelhardt
@ 2009-09-24  8:30   ` Shai Tahar
  2009-09-24 11:26     ` Amos Jeffries
  0 siblings, 1 reply; 6+ messages in thread
From: Shai Tahar @ 2009-09-24  8:30 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: netfilter-devel, bdschuym, shai.tahar

in case you manipulate the data in the connection, such as in tproxy 
scenario (squid etc')
a new connection goes out (with the same tuple) but the mac address is 
diffrent (the source mac is the device interface)

assuming A,B,C are mac address and 1,2,3 are ip address

[user]<--->[transparent bridge]<--->[server]
A1 B2 C3

user initiates a connection A1--->C3
the connection is redirected into B2, the connection is terminated as a 
socket to a local application on the traparent bridge machine.

a new connection goes out from B2, masked as B1--->C3 (the target 
changes B1 into A1)
in return, the server answers A1 C3--->A1, the connection is redirected 
into the localhost
the data then forwarded to the user B3--->A1 (the target changes B3 int C3)

Shai Tahar
Storwize

Jan Engelhardt wrote:
> On Thursday 2009-09-24 09:43, Shai Tahar wrote:
>
>   
>> ---- README ---
>> ebt_dyn_snat - ebtable dynamic snat
>>    Authors:
>>      Shai Tahar <shai.tahar@storwize.com>
>>
>>    Changes source mac address according to source ip address based on local
>> arp table
>>    to be used when source ip address is snated
>>
>> Copyright (C) 2009 Storwize
>>
>> ebtables target for transparent bridge
>> [user]<--->[transparent bridge]<--->[server]
>>
>> if the transparent bridge maskes user ip address towards the server,
>> the bridge normally would replace the source mac address
>>     
>
> Well, if you want to have the client's original MAC address in the
> packet, do not SNAT it. It (seems) as simple as that.
>   


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: new target - ebtables dynamic snat, kernel and userspace patch
  2009-09-24  8:30   ` Shai Tahar
@ 2009-09-24 11:26     ` Amos Jeffries
  2009-09-25  1:04       ` Philip Craig
  0 siblings, 1 reply; 6+ messages in thread
From: Amos Jeffries @ 2009-09-24 11:26 UTC (permalink / raw)
  To: Shai Tahar; +Cc: Jan Engelhardt, netfilter-devel, bdschuym, shai.tahar

Shai Tahar wrote:
> in case you manipulate the data in the connection, such as in tproxy 
> scenario (squid etc')
> a new connection goes out (with the same tuple) but the mac address is 
> diffrent (the source mac is the device interface)
> 
> assuming A,B,C are mac address and 1,2,3 are ip address
> 
> [user]<--->[transparent bridge]<--->[server]
> A1 B2 C3
> 

Your next steps misunderstand how MAC addresses work. MAC changes at 
each physical NIC card plugged into the cable.

Corrections follow...

> user initiates a connection A1--->C3

Correction:
  user initiates query A1---->?3
  network responds  ===> go to 3 via B
  user initiates connection A1--->B3


> the connection is redirected into B2,

Correction:
    the connection succeeds.
    packets get forwarded

NORMAL OPERATION:
    B2 relays packets to C3...
    server sends reply packets C3--->B1

   B2 proceeds to shuffle packets like so
    out A1-->B3::B1-->C3
    and back C3-->B1::B3-->A1

> the connection is terminated as a 
> socket to a local application on the traparent bridge machine.

YOUR SCENARIO OPERATION:

   B2 relays packets to local app.

   local app initiates query B1---->?3
   network responds  ===> go to 3 via C
   local app initiates connection B1--->C3


   B2 proceeds to shuffle packets like so
    out A1-->B3:local-app:B1-->C3
    and back  C3-->B1:local-app:B3-->A1


As you can see there is no difference between normal correct MAC 
operation and the existing tproxy scenario as viewed by C3 and A1.


AYJ

> 
> a new connection goes out from B2, masked as B1--->C3 (the target 
> changes B1 into A1)
> in return, the server answers A1 C3--->A1, the connection is redirected 
> into the localhost
> the data then forwarded to the user B3--->A1 (the target changes B3 int C3)
> 
> Shai Tahar
> Storwize
> 
> Jan Engelhardt wrote:
>> On Thursday 2009-09-24 09:43, Shai Tahar wrote:
>>
>>  
>>> ---- README ---
>>> ebt_dyn_snat - ebtable dynamic snat
>>>    Authors:
>>>      Shai Tahar <shai.tahar@storwize.com>
>>>
>>>    Changes source mac address according to source ip address based on 
>>> local
>>> arp table
>>>    to be used when source ip address is snated
>>>
>>> Copyright (C) 2009 Storwize
>>>
>>> ebtables target for transparent bridge
>>> [user]<--->[transparent bridge]<--->[server]
>>>
>>> if the transparent bridge maskes user ip address towards the server,
>>> the bridge normally would replace the source mac address
>>>     
>>
>> Well, if you want to have the client's original MAC address in the
>> packet, do not SNAT it. It (seems) as simple as that.
>>   

Even better, plug the client machine directly into the server NIC.

Amos
-- 
Please be using
   Current Stable Squid 2.7.STABLE7 or 3.0.STABLE19
   Current Beta Squid 3.1.0.13

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: new target - ebtables dynamic snat, kernel and userspace patch
  2009-09-24  7:43 new target - ebtables dynamic snat, kernel and userspace patch Shai Tahar
  2009-09-24  8:12 ` Jan Engelhardt
@ 2009-09-24 20:24 ` Bart De Schuymer
  1 sibling, 0 replies; 6+ messages in thread
From: Bart De Schuymer @ 2009-09-24 20:24 UTC (permalink / raw)
  To: Shai Tahar; +Cc: netfilter-devel, shai.tahar

Shai Tahar schreef:
> ---- README ---
> ebt_dyn_snat - ebtable dynamic snat
>     Authors:
>       Shai Tahar <shai.tahar@storwize.com>
>
>     Changes source mac address according to source ip address based on 
> local arp table
>     to be used when source ip address is snated
>
Hi,

A few comments/questions.
Why is the standard target DROP?
Please provide a man file entry (ebtables.8)
You didn't provide the configuration option for the kernel
Please provide the patches as attachments (separate files for kernel and 
userspace) that will patch correctly with 'patch -p1 < $file'
After a first glance the code looks ok.
Maybe the description of your target should be more general: it matches 
the ARP source address to the IP source address based on the local arp 
table. Your target is indeed useful to make a bridging firewall that 
does IP NAT more transparent.

cheers,
Bart


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: new target - ebtables dynamic snat, kernel and userspace patch
  2009-09-24 11:26     ` Amos Jeffries
@ 2009-09-25  1:04       ` Philip Craig
  0 siblings, 0 replies; 6+ messages in thread
From: Philip Craig @ 2009-09-25  1:04 UTC (permalink / raw)
  To: Amos Jeffries
  Cc: Shai Tahar, Jan Engelhardt, netfilter-devel, bdschuym, shai.tahar

Amos Jeffries wrote:
> Shai Tahar wrote:
>> in case you manipulate the data in the connection, such as in tproxy 
>> scenario (squid etc')
>> a new connection goes out (with the same tuple) but the mac address is 
>> diffrent (the source mac is the device interface)
>>
>> assuming A,B,C are mac address and 1,2,3 are ip address
>>
>> [user]<--->[transparent bridge]<--->[server]
>> A1 B2 C3
>>
> 
> Your next steps misunderstand how MAC addresses work. MAC changes at 
> each physical NIC card plugged into the cable.

Not necessarily, and not for a bridge.  That's why bridges put the
NIC in promiscuous mode.

> Corrections follow...
> 
>> user initiates a connection A1--->C3
> 
> Correction:
>   user initiates query A1---->?3
>   network responds  ===> go to 3 via B
>   user initiates connection A1--->B3

That's how proxy arp works, not bridging.  A bridge knows nothing
about IP, it just forwards packets unmodified to the destination
MAC address.


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2009-09-25  1:08 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-09-24  7:43 new target - ebtables dynamic snat, kernel and userspace patch Shai Tahar
2009-09-24  8:12 ` Jan Engelhardt
2009-09-24  8:30   ` Shai Tahar
2009-09-24 11:26     ` Amos Jeffries
2009-09-25  1:04       ` Philip Craig
2009-09-24 20:24 ` Bart De Schuymer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).