aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorHannes Eder <heder@google.com>2010-07-23 06:46:32 -0400
committerPatrick McHardy <kaber@trash.net>2010-07-23 06:46:32 -0400
commit7b215ffc3885a38182d3d49ceb41d0a81c3e041a (patch)
tree65172fb8eec92848efee3b76f32ff3dabc4c84fa /net
parent9c3e1c39679144c250dda95098333ecb5f1f407a (diff)
IPVS: make friends with nf_conntrack
Update the nf_conntrack tuple in reply direction, as we will see traffic from the real server (RIP) to the client (CIP). Once this is done we can use netfilters SNAT in POSTROUTING, especially with xt_ipvs, to do source NAT, e.g.: % iptables -t nat -A POSTROUTING -m ipvs --vaddr 192.168.100.30/32 --vport 80 \ -j SNAT --to-source 192.168.10.10 [ minor fixes by Simon Horman <horms@verge.net.au> ] Signed-off-by: Hannes Eder <heder@google.com> Signed-off-by: Simon Horman <horms@verge.net.au> Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/ipvs/Kconfig2
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c36
-rw-r--r--net/netfilter/ipvs/ip_vs_xmit.c29
3 files changed, 30 insertions, 37 deletions
diff --git a/net/netfilter/ipvs/Kconfig b/net/netfilter/ipvs/Kconfig
index d80b41abec0..366244492ac 100644
--- a/net/netfilter/ipvs/Kconfig
+++ b/net/netfilter/ipvs/Kconfig
@@ -3,7 +3,7 @@
3# 3#
4menuconfig IP_VS 4menuconfig IP_VS
5 tristate "IP virtual server support" 5 tristate "IP virtual server support"
6 depends on NET && INET && NETFILTER 6 depends on NET && INET && NETFILTER && NF_CONNTRACK
7 ---help--- 7 ---help---
8 IP Virtual Server support will let you build a high-performance 8 IP Virtual Server support will let you build a high-performance
9 virtual server based on cluster of two or more real servers. This 9 virtual server based on cluster of two or more real servers. This
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 50907d8472a..58f82dfc950 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -536,26 +536,6 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
536 return NF_DROP; 536 return NF_DROP;
537} 537}
538 538
539
540/*
541 * It is hooked before NF_IP_PRI_NAT_SRC at the NF_INET_POST_ROUTING
542 * chain, and is used for VS/NAT.
543 * It detects packets for VS/NAT connections and sends the packets
544 * immediately. This can avoid that iptable_nat mangles the packets
545 * for VS/NAT.
546 */
547static unsigned int ip_vs_post_routing(unsigned int hooknum,
548 struct sk_buff *skb,
549 const struct net_device *in,
550 const struct net_device *out,
551 int (*okfn)(struct sk_buff *))
552{
553 if (!skb->ipvs_property)
554 return NF_ACCEPT;
555 /* The packet was sent from IPVS, exit this chain */
556 return NF_STOP;
557}
558
559__sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset) 539__sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset)
560{ 540{
561 return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0)); 541 return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0));
@@ -1499,14 +1479,6 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
1499 .hooknum = NF_INET_FORWARD, 1479 .hooknum = NF_INET_FORWARD,
1500 .priority = 99, 1480 .priority = 99,
1501 }, 1481 },
1502 /* Before the netfilter connection tracking, exit from POST_ROUTING */
1503 {
1504 .hook = ip_vs_post_routing,
1505 .owner = THIS_MODULE,
1506 .pf = PF_INET,
1507 .hooknum = NF_INET_POST_ROUTING,
1508 .priority = NF_IP_PRI_NAT_SRC-1,
1509 },
1510#ifdef CONFIG_IP_VS_IPV6 1482#ifdef CONFIG_IP_VS_IPV6
1511 /* After packet filtering, forward packet through VS/DR, VS/TUN, 1483 /* After packet filtering, forward packet through VS/DR, VS/TUN,
1512 * or VS/NAT(change destination), so that filtering rules can be 1484 * or VS/NAT(change destination), so that filtering rules can be
@@ -1535,14 +1507,6 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
1535 .hooknum = NF_INET_FORWARD, 1507 .hooknum = NF_INET_FORWARD,
1536 .priority = 99, 1508 .priority = 99,
1537 }, 1509 },
1538 /* Before the netfilter connection tracking, exit from POST_ROUTING */
1539 {
1540 .hook = ip_vs_post_routing,
1541 .owner = THIS_MODULE,
1542 .pf = PF_INET6,
1543 .hooknum = NF_INET_POST_ROUTING,
1544 .priority = NF_IP6_PRI_NAT_SRC-1,
1545 },
1546#endif 1510#endif
1547}; 1511};
1548 1512
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index 02b078e11cf..21e1a5e9b9d 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -28,6 +28,7 @@
28#include <net/ip6_route.h> 28#include <net/ip6_route.h>
29#include <linux/icmpv6.h> 29#include <linux/icmpv6.h>
30#include <linux/netfilter.h> 30#include <linux/netfilter.h>
31#include <net/netfilter/nf_conntrack.h>
31#include <linux/netfilter_ipv4.h> 32#include <linux/netfilter_ipv4.h>
32 33
33#include <net/ip_vs.h> 34#include <net/ip_vs.h>
@@ -348,6 +349,30 @@ ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
348} 349}
349#endif 350#endif
350 351
352static void
353ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp)
354{
355 struct nf_conn *ct = (struct nf_conn *)skb->nfct;
356 struct nf_conntrack_tuple new_tuple;
357
358 if (ct == NULL || nf_ct_is_untracked(ct) || nf_ct_is_confirmed(ct))
359 return;
360
361 /*
362 * The connection is not yet in the hashtable, so we update it.
363 * CIP->VIP will remain the same, so leave the tuple in
364 * IP_CT_DIR_ORIGINAL untouched. When the reply comes back from the
365 * real-server we will see RIP->DIP.
366 */
367 new_tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
368 new_tuple.src.u3 = cp->daddr;
369 /*
370 * This will also take care of UDP and other protocols.
371 */
372 new_tuple.src.u.tcp.port = cp->dport;
373 nf_conntrack_alter_reply(ct, &new_tuple);
374}
375
351/* 376/*
352 * NAT transmitter (only for outside-to-inside nat forwarding) 377 * NAT transmitter (only for outside-to-inside nat forwarding)
353 * Not used for related ICMP 378 * Not used for related ICMP
@@ -403,6 +428,8 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
403 428
404 IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT"); 429 IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT");
405 430
431 ip_vs_update_conntrack(skb, cp);
432
406 /* FIXME: when application helper enlarges the packet and the length 433 /* FIXME: when application helper enlarges the packet and the length
407 is larger than the MTU of outgoing device, there will be still 434 is larger than the MTU of outgoing device, there will be still
408 MTU problem. */ 435 MTU problem. */
@@ -479,6 +506,8 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
479 506
480 IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT"); 507 IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT");
481 508
509 ip_vs_update_conntrack(skb, cp);
510
482 /* FIXME: when application helper enlarges the packet and the length 511 /* FIXME: when application helper enlarges the packet and the length
483 is larger than the MTU of outgoing device, there will be still 512 is larger than the MTU of outgoing device, there will be still
484 MTU problem. */ 513 MTU problem. */