All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 13/13] TProxy: use the interface primary IP address as a default value for --on-ip
@ 2009-09-21 14:46 Balazs Scheidler
  2009-09-21 18:00 ` Brian Haley
  0 siblings, 1 reply; 6+ messages in thread
From: Balazs Scheidler @ 2009-09-21 14:46 UTC (permalink / raw)
  To: netfilter-devel, netdev

The REDIRECT target and the older TProxy versions used the primary address
of the incoming interface as the default value of the --on-ip parameter.
This was unintentionally changed during the initial TProxy submission and
caused confusion among users.

This is implemented for both IPv4 and IPv6.

Signed-off-by: Balazs Scheidler <bazsi@balabit.hu>
---
 net/netfilter/xt_TPROXY.c |   63 ++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 56 insertions(+), 7 deletions(-)

diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c
index 4a345cd..b99e2b5 100644
--- a/net/netfilter/xt_TPROXY.c
+++ b/net/netfilter/xt_TPROXY.c
@@ -16,15 +16,41 @@
 #include <net/checksum.h>
 #include <net/udp.h>
 #include <net/inet_sock.h>
-
+#include <linux/inetdevice.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-#include <linux/netfilter/xt_TPROXY.h>
 
 #include <net/netfilter/ipv4/nf_defrag_ipv4.h>
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#include <net/if_inet6.h>
+#include <net/addrconf.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
 #include <net/netfilter/ipv6/nf_defrag_ipv6.h>
+#endif
+
 #include <net/netfilter/nf_tproxy_core.h>
+#include <linux/netfilter/xt_TPROXY.h>
+
+static inline __be32
+tproxy_laddr4(struct sk_buff *skb, __be32 user_laddr, __be32 daddr)
+{
+	struct in_device *indev;
+	__be32 laddr;
+	
+        if (user_laddr)
+                return user_laddr;
+	
+        laddr = 0;
+        rcu_read_lock();
+        indev = __in_dev_get_rcu(skb->dev);
+        for_primary_ifa(indev) {
+		laddr = ifa->ifa_local;
+                break;
+        } endfor_ifa(indev);
+        rcu_read_unlock();
+        
+        return laddr ? laddr : daddr;
+}
 
 static unsigned int
 tproxy_tg4(struct sk_buff *skb, __be32 laddr, __be16 lport, u_int32_t mark_mask, u_int32_t mark_value)
@@ -63,7 +89,7 @@ tproxy_tg4(struct sk_buff *skb, __be32 laddr, __be16 lport, u_int32_t mark_mask,
 			 * there's a listener on the redirected port
 			 */
 			sk2 = nf_tproxy_get_sock_v4(dev_net(skb->dev), iph->protocol,
-						    iph->saddr, laddr ? laddr : iph->daddr,
+						    iph->saddr, tproxy_laddr4(skb, laddr, iph->daddr),
 						    hp->source, lport ? lport : hp->dest,
 						    skb->dev, NFT_LOOKUP_LISTENER);
 			if (sk2) {
@@ -80,7 +106,7 @@ tproxy_tg4(struct sk_buff *skb, __be32 laddr, __be16 lport, u_int32_t mark_mask,
 		/* no there's no established connection, check if
 		 * there's a listener on the redirected addr/port */
 		sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), iph->protocol,
-					   iph->saddr, laddr ? laddr : iph->daddr,
+					   iph->saddr, tproxy_laddr4(skb, laddr, iph->daddr),
 					   hp->source, lport ? lport : hp->dest,
 					   skb->dev, NFT_LOOKUP_LISTENER);
 	}
@@ -119,6 +145,29 @@ tproxy_tg4_v1(struct sk_buff *skb, const struct xt_target_param *par)
 }
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+
+static inline const struct in6_addr *
+tproxy_laddr6(struct sk_buff *skb, const struct in6_addr *user_laddr, const struct in6_addr *daddr)
+{
+	struct inet6_dev *indev;
+	struct inet6_ifaddr *ifa;
+	struct in6_addr *laddr;
+	
+        if (!ipv6_addr_any(user_laddr))
+                return user_laddr;
+	
+        laddr = NULL;
+        rcu_read_lock();
+        indev = __in6_dev_get(skb->dev);
+        if (indev && (ifa = indev->addr_list)) {
+		laddr = &ifa->addr;
+	}
+        rcu_read_unlock();
+        
+        return laddr ? laddr : daddr;
+}
+
+
 static unsigned int
 tproxy_tg6_v1(struct sk_buff *skb, const struct xt_target_param *par)
 {
@@ -168,7 +217,7 @@ tproxy_tg6_v1(struct sk_buff *skb, const struct xt_target_param *par)
 			 * there's a listener on the redirected port
 			 */
 			sk2 = nf_tproxy_get_sock_v6(dev_net(skb->dev), tproto,
-						    &iph->saddr, !ipv6_addr_any(&tgi->laddr.in6) ? &tgi->laddr.in6 : &iph->daddr,
+						    &iph->saddr, tproxy_laddr6(skb, &tgi->laddr.in6, &iph->daddr),
 						    hp->source, tgi->lport ? tgi->lport : hp->dest,
 						    par->in, NFT_LOOKUP_LISTENER);
 			if (sk2) {
@@ -185,7 +234,7 @@ tproxy_tg6_v1(struct sk_buff *skb, const struct xt_target_param *par)
 		/* no there's no established connection, check if
 		 * there's a listener on the redirected addr/port */
 		sk = nf_tproxy_get_sock_v6(dev_net(skb->dev), tproto,
-					   &iph->saddr, !ipv6_addr_any(&tgi->laddr.in6) ? &tgi->laddr.in6 : &iph->daddr,
+					   &iph->saddr, tproxy_laddr6(skb, &tgi->laddr.in6, &iph->daddr),
 					   hp->source, tgi->lport ? tgi->lport : hp->dest,
 					   par->in, NFT_LOOKUP_LISTENER);
 	}
-- 
1.6.0.4


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

* Re: [PATCH 13/13] TProxy: use the interface primary IP address as a default value for --on-ip
  2009-09-21 14:46 [PATCH 13/13] TProxy: use the interface primary IP address as a default value for --on-ip Balazs Scheidler
@ 2009-09-21 18:00 ` Brian Haley
  2009-09-22  6:38   ` Balazs Scheidler
  0 siblings, 1 reply; 6+ messages in thread
From: Brian Haley @ 2009-09-21 18:00 UTC (permalink / raw)
  To: Balazs Scheidler; +Cc: netfilter-devel, netdev

Balazs Scheidler wrote: 
>  #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
> +
> +static inline const struct in6_addr *
> +tproxy_laddr6(struct sk_buff *skb, const struct in6_addr *user_laddr, const struct in6_addr *daddr)
> +{
> +	struct inet6_dev *indev;
> +	struct inet6_ifaddr *ifa;
> +	struct in6_addr *laddr;
> +	
> +        if (!ipv6_addr_any(user_laddr))
> +                return user_laddr;
> +	
> +        laddr = NULL;
> +        rcu_read_lock();
> +        indev = __in6_dev_get(skb->dev);
> +        if (indev && (ifa = indev->addr_list)) {
> +		laddr = &ifa->addr;
> +	}
> +        rcu_read_unlock();
> +        
> +        return laddr ? laddr : daddr;
> +}

You should call ipv6_dev_get_saddr() to get a source address based on the target
destination address.

-Brian

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

* Re: [PATCH 13/13] TProxy: use the interface primary IP address as a default value for --on-ip
  2009-09-21 18:00 ` Brian Haley
@ 2009-09-22  6:38   ` Balazs Scheidler
  2009-09-22 14:17     ` Brian Haley
  0 siblings, 1 reply; 6+ messages in thread
From: Balazs Scheidler @ 2009-09-22  6:38 UTC (permalink / raw)
  To: Brian Haley; +Cc: netfilter-devel, netdev

On Mon, 2009-09-21 at 14:00 -0400, Brian Haley wrote:
> Balazs Scheidler wrote: 
> >  #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
> > +
> > +static inline const struct in6_addr *
> > +tproxy_laddr6(struct sk_buff *skb, const struct in6_addr *user_laddr, const struct in6_addr *daddr)
> > +{
> > +	struct inet6_dev *indev;
> > +	struct inet6_ifaddr *ifa;
> > +	struct in6_addr *laddr;
> > +	
> > +        if (!ipv6_addr_any(user_laddr))
> > +                return user_laddr;
> > +	
> > +        laddr = NULL;
> > +        rcu_read_lock();
> > +        indev = __in6_dev_get(skb->dev);
> > +        if (indev && (ifa = indev->addr_list)) {
> > +		laddr = &ifa->addr;
> > +	}
> > +        rcu_read_unlock();
> > +        
> > +        return laddr ? laddr : daddr;
> > +}
> 
> You should call ipv6_dev_get_saddr() to get a source address based on the target
> destination address.

Thanks for this hint, however this is not selecting a source address for
a given destination, rather it selects the address where tproxy is
redirecting the connection in case the user specified no --on-ip
parameter.

e.g. 

ip6tables -A PREROUTING -p tcp --dport 80 -j TPROXY --on-port 50080

This should redirect the connection to the primary IP address of the
incoming interface. In fact I spent 2 hours to figure out how to find
the proper address, and at the end I used the first IP address
configured to the interface, seeing that those addresses are sorted in
'scope' order, e.g. link-local and site-local addresses are at the end
of the list, thus the front should be ok.

Since I'm not that much into IPv6, I'd appreciate some help, is
ipv6_dev_get_saddr(client_ip_address) indeed the best solution here?

-- 
Bazsi


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

* Re: [PATCH 13/13] TProxy: use the interface primary IP address as a default value for --on-ip
  2009-09-22  6:38   ` Balazs Scheidler
@ 2009-09-22 14:17     ` Brian Haley
  2009-09-25 18:07       ` Balazs Scheidler
  0 siblings, 1 reply; 6+ messages in thread
From: Brian Haley @ 2009-09-22 14:17 UTC (permalink / raw)
  To: Balazs Scheidler; +Cc: netfilter-devel, netdev

Balazs Scheidler wrote:
> On Mon, 2009-09-21 at 14:00 -0400, Brian Haley wrote:
>> Balazs Scheidler wrote: 
>>>  #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
>>> +
>>> +static inline const struct in6_addr *
>>> +tproxy_laddr6(struct sk_buff *skb, const struct in6_addr *user_laddr, const struct in6_addr *daddr)
>>> +{
>>> +	struct inet6_dev *indev;
>>> +	struct inet6_ifaddr *ifa;
>>> +	struct in6_addr *laddr;
>>> +	
>>> +        if (!ipv6_addr_any(user_laddr))
>>> +                return user_laddr;
>>> +	
>>> +        laddr = NULL;
>>> +        rcu_read_lock();
>>> +        indev = __in6_dev_get(skb->dev);
>>> +        if (indev && (ifa = indev->addr_list)) {
>>> +		laddr = &ifa->addr;
>>> +	}
>>> +        rcu_read_unlock();
>>> +        
>>> +        return laddr ? laddr : daddr;
>>> +}
>> You should call ipv6_dev_get_saddr() to get a source address based on the target
>> destination address.
> 
> Thanks for this hint, however this is not selecting a source address for
> a given destination, rather it selects the address where tproxy is
> redirecting the connection in case the user specified no --on-ip
> parameter.
> 
> e.g. 
> 
> ip6tables -A PREROUTING -p tcp --dport 80 -j TPROXY --on-port 50080
> 
> This should redirect the connection to the primary IP address of the
> incoming interface. In fact I spent 2 hours to figure out how to find
> the proper address, and at the end I used the first IP address
> configured to the interface, seeing that those addresses are sorted in
> 'scope' order, e.g. link-local and site-local addresses are at the end
> of the list, thus the front should be ok.

Yes, the addresses are sorted by scope, but just because they're in the
list doesn't mean they can be used, for example that address might have
failed DAD or be Deprecated.  ipv6_dev_get_saddr() will follow the rules
from RFC 3484 in picking the best address to use, or none if there isn't
anything appropriate.

> Since I'm not that much into IPv6, I'd appreciate some help, is
> ipv6_dev_get_saddr(client_ip_address) indeed the best solution here?

Probably.  An alternative might be to use ip6_dst_lookup() (see tcp_v6_connect()),
but a lot more code for you.

-Brian

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

* Re: [PATCH 13/13] TProxy: use the interface primary IP address as a default value for --on-ip
  2009-09-22 14:17     ` Brian Haley
@ 2009-09-25 18:07       ` Balazs Scheidler
  2009-09-28 16:16         ` Brian Haley
  0 siblings, 1 reply; 6+ messages in thread
From: Balazs Scheidler @ 2009-09-25 18:07 UTC (permalink / raw)
  To: Brian Haley; +Cc: netfilter-devel, netdev

On Tue, 2009-09-22 at 10:17 -0400, Brian Haley wrote:
> Balazs Scheidler wrote:
> > On Mon, 2009-09-21 at 14:00 -0400, Brian Haley wrote:
> >> Balazs Scheidler wrote: 
> >>>  #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
> >>> +
> >>> +static inline const struct in6_addr *
> >>> +tproxy_laddr6(struct sk_buff *skb, const struct in6_addr *user_laddr, const struct in6_addr *daddr)
> >>> +{
> >>> +	struct inet6_dev *indev;
> >>> +	struct inet6_ifaddr *ifa;
> >>> +	struct in6_addr *laddr;
> >>> +	
> >>> +        if (!ipv6_addr_any(user_laddr))
> >>> +                return user_laddr;
> >>> +	
> >>> +        laddr = NULL;
> >>> +        rcu_read_lock();
> >>> +        indev = __in6_dev_get(skb->dev);
> >>> +        if (indev && (ifa = indev->addr_list)) {
> >>> +		laddr = &ifa->addr;
> >>> +	}
> >>> +        rcu_read_unlock();
> >>> +        
> >>> +        return laddr ? laddr : daddr;
> >>> +}
> >> You should call ipv6_dev_get_saddr() to get a source address based on the target
> >> destination address.
> > 
> > Thanks for this hint, however this is not selecting a source address for
> > a given destination, rather it selects the address where tproxy is
> > redirecting the connection in case the user specified no --on-ip
> > parameter.
> > 
> > e.g. 
> > 
> > ip6tables -A PREROUTING -p tcp --dport 80 -j TPROXY --on-port 50080
> > 
> > This should redirect the connection to the primary IP address of the
> > incoming interface. In fact I spent 2 hours to figure out how to find
> > the proper address, and at the end I used the first IP address
> > configured to the interface, seeing that those addresses are sorted in
> > 'scope' order, e.g. link-local and site-local addresses are at the end
> > of the list, thus the front should be ok.
> 
> Yes, the addresses are sorted by scope, but just because they're in the
> list doesn't mean they can be used, for example that address might have
> failed DAD or be Deprecated.  ipv6_dev_get_saddr() will follow the rules
> from RFC 3484 in picking the best address to use, or none if there isn't
> anything appropriate.
> 
> > Since I'm not that much into IPv6, I'd appreciate some help, is
> > ipv6_dev_get_saddr(client_ip_address) indeed the best solution here?
> 
> Probably.  An alternative might be to use ip6_dst_lookup() (see tcp_v6_connect()),
> but a lot more code for you.

One question, how fast is ipv6_dev_get_saddr()? Since the TPROXY target
can execute on a per-packet path (although the socket match should take
care of packets that belong to already-established connections), this
may be performance critical. Is ipv6_dev_get_saddr() something that I
can call so often?

-- 
Bazsi



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

* Re: [PATCH 13/13] TProxy: use the interface primary IP address as a default value for --on-ip
  2009-09-25 18:07       ` Balazs Scheidler
@ 2009-09-28 16:16         ` Brian Haley
  0 siblings, 0 replies; 6+ messages in thread
From: Brian Haley @ 2009-09-28 16:16 UTC (permalink / raw)
  To: Balazs Scheidler; +Cc: netfilter-devel, netdev

Balazs Scheidler wrote:
> One question, how fast is ipv6_dev_get_saddr()? Since the TPROXY target
> can execute on a per-packet path (although the socket match should take
> care of packets that belong to already-established connections), this
> may be performance critical. Is ipv6_dev_get_saddr() something that I
> can call so often?

It probably isn't the best thing to be calling on a per-packet basis, it's
mainly called now on a per-connection basis.  I guess if it's really bad
for you we could do something like ipv6_get_lladdr() does for finding
a link-local address, it might be good enough in this case.

-Brian

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

end of thread, other threads:[~2009-09-28 16:16 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-09-21 14:46 [PATCH 13/13] TProxy: use the interface primary IP address as a default value for --on-ip Balazs Scheidler
2009-09-21 18:00 ` Brian Haley
2009-09-22  6:38   ` Balazs Scheidler
2009-09-22 14:17     ` Brian Haley
2009-09-25 18:07       ` Balazs Scheidler
2009-09-28 16:16         ` Brian Haley

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.