diff options
author | Julian Anastasov <ja@ssi.bg> | 2010-09-21 11:38:57 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2010-09-21 11:38:57 -0400 |
commit | 8a8030407f55a6aaedb51167c1a2383311fcd707 (patch) | |
tree | 585f2963a56e528a06f0f3180985faa8a368d3b8 | |
parent | f4bc17cdd205ebaa3807c2aa973719bb5ce6a5b2 (diff) |
ipvs: make rerouting optional with snat_reroute
Add new sysctl flag "snat_reroute". Recent kernels use
ip_route_me_harder() to route LVS-NAT responses properly by
VIP when there are multiple paths to client. But setups
that do not have alternative default routes can skip this
routing lookup by using snat_reroute=0.
Signed-off-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r-- | include/net/ip_vs.h | 1 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_core.c | 37 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_ctl.c | 8 |
3 files changed, 38 insertions, 8 deletions
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index e8ec5231eae9..3915a4f4cd30 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h | |||
@@ -801,6 +801,7 @@ extern int sysctl_ip_vs_expire_quiescent_template; | |||
801 | extern int sysctl_ip_vs_sync_threshold[2]; | 801 | extern int sysctl_ip_vs_sync_threshold[2]; |
802 | extern int sysctl_ip_vs_nat_icmp_send; | 802 | extern int sysctl_ip_vs_nat_icmp_send; |
803 | extern int sysctl_ip_vs_conntrack; | 803 | extern int sysctl_ip_vs_conntrack; |
804 | extern int sysctl_ip_vs_snat_reroute; | ||
804 | extern struct ip_vs_stats ip_vs_stats; | 805 | extern struct ip_vs_stats ip_vs_stats; |
805 | extern const struct ctl_path net_vs_ctl_path[]; | 806 | extern const struct ctl_path net_vs_ctl_path[]; |
806 | 807 | ||
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 7fbc80d81fe8..06c388bf4e33 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c | |||
@@ -929,20 +929,31 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, | |||
929 | ip_send_check(ip_hdr(skb)); | 929 | ip_send_check(ip_hdr(skb)); |
930 | } | 930 | } |
931 | 931 | ||
932 | /* | ||
933 | * nf_iterate does not expect change in the skb->dst->dev. | ||
934 | * It looks like it is not fatal to enable this code for hooks | ||
935 | * where our handlers are at the end of the chain list and | ||
936 | * when all next handlers use skb->dst->dev and not outdev. | ||
937 | * It will definitely route properly the inout NAT traffic | ||
938 | * when multiple paths are used. | ||
939 | */ | ||
940 | |||
932 | /* For policy routing, packets originating from this | 941 | /* For policy routing, packets originating from this |
933 | * machine itself may be routed differently to packets | 942 | * machine itself may be routed differently to packets |
934 | * passing through. We want this packet to be routed as | 943 | * passing through. We want this packet to be routed as |
935 | * if it came from this machine itself. So re-compute | 944 | * if it came from this machine itself. So re-compute |
936 | * the routing information. | 945 | * the routing information. |
937 | */ | 946 | */ |
947 | if (sysctl_ip_vs_snat_reroute) { | ||
938 | #ifdef CONFIG_IP_VS_IPV6 | 948 | #ifdef CONFIG_IP_VS_IPV6 |
939 | if (af == AF_INET6) { | 949 | if (af == AF_INET6) { |
940 | if (ip6_route_me_harder(skb) != 0) | 950 | if (ip6_route_me_harder(skb) != 0) |
941 | goto drop; | 951 | goto drop; |
942 | } else | 952 | } else |
943 | #endif | 953 | #endif |
944 | if (ip_route_me_harder(skb, RTN_LOCAL) != 0) | 954 | if (ip_route_me_harder(skb, RTN_LOCAL) != 0) |
945 | goto drop; | 955 | goto drop; |
956 | } | ||
946 | 957 | ||
947 | IP_VS_DBG_PKT(10, pp, skb, 0, "After SNAT"); | 958 | IP_VS_DBG_PKT(10, pp, skb, 0, "After SNAT"); |
948 | 959 | ||
@@ -991,8 +1002,13 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, | |||
991 | if (unlikely(iph.protocol == IPPROTO_ICMPV6)) { | 1002 | if (unlikely(iph.protocol == IPPROTO_ICMPV6)) { |
992 | int related, verdict = ip_vs_out_icmp_v6(skb, &related); | 1003 | int related, verdict = ip_vs_out_icmp_v6(skb, &related); |
993 | 1004 | ||
994 | if (related) | 1005 | if (related) { |
1006 | if (sysctl_ip_vs_snat_reroute && | ||
1007 | NF_ACCEPT == verdict && | ||
1008 | ip6_route_me_harder(skb)) | ||
1009 | verdict = NF_DROP; | ||
995 | return verdict; | 1010 | return verdict; |
1011 | } | ||
996 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); | 1012 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); |
997 | } | 1013 | } |
998 | } else | 1014 | } else |
@@ -1000,8 +1016,13 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, | |||
1000 | if (unlikely(iph.protocol == IPPROTO_ICMP)) { | 1016 | if (unlikely(iph.protocol == IPPROTO_ICMP)) { |
1001 | int related, verdict = ip_vs_out_icmp(skb, &related); | 1017 | int related, verdict = ip_vs_out_icmp(skb, &related); |
1002 | 1018 | ||
1003 | if (related) | 1019 | if (related) { |
1020 | if (sysctl_ip_vs_snat_reroute && | ||
1021 | NF_ACCEPT == verdict && | ||
1022 | ip_route_me_harder(skb, RTN_LOCAL)) | ||
1023 | verdict = NF_DROP; | ||
1004 | return verdict; | 1024 | return verdict; |
1025 | } | ||
1005 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); | 1026 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); |
1006 | } | 1027 | } |
1007 | 1028 | ||
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index d2d842f292c6..e637cd0384b1 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c | |||
@@ -91,6 +91,7 @@ int sysctl_ip_vs_nat_icmp_send = 0; | |||
91 | #ifdef CONFIG_IP_VS_NFCT | 91 | #ifdef CONFIG_IP_VS_NFCT |
92 | int sysctl_ip_vs_conntrack; | 92 | int sysctl_ip_vs_conntrack; |
93 | #endif | 93 | #endif |
94 | int sysctl_ip_vs_snat_reroute = 1; | ||
94 | 95 | ||
95 | 96 | ||
96 | #ifdef CONFIG_IP_VS_DEBUG | 97 | #ifdef CONFIG_IP_VS_DEBUG |
@@ -1599,6 +1600,13 @@ static struct ctl_table vs_vars[] = { | |||
1599 | .mode = 0644, | 1600 | .mode = 0644, |
1600 | .proc_handler = proc_do_defense_mode, | 1601 | .proc_handler = proc_do_defense_mode, |
1601 | }, | 1602 | }, |
1603 | { | ||
1604 | .procname = "snat_reroute", | ||
1605 | .data = &sysctl_ip_vs_snat_reroute, | ||
1606 | .maxlen = sizeof(int), | ||
1607 | .mode = 0644, | ||
1608 | .proc_handler = &proc_dointvec, | ||
1609 | }, | ||
1602 | #if 0 | 1610 | #if 0 |
1603 | { | 1611 | { |
1604 | .procname = "timeout_established", | 1612 | .procname = "timeout_established", |