From: Amos Jeffries Date: Tue, 15 Sep 2009 11:59:51 +0000 (+1200) Subject: Auto-detect the amount of TPROXY support available. X-Git-Tag: SQUID_3_2_0_1~721 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=263f84f0b10fce36ff6e147d91677328effe20c9;p=thirdparty%2Fsquid.git Auto-detect the amount of TPROXY support available. Uses the configured port address type to determine the level of testing done. Systems with IPv4-only TPROXY (kernel 2.6.28 to 2.6.3*) will have their ports reduced to IPv4-only, and those with IPv6 support will see the port open as IPv6. This is done a run-time to cater for patched kernels and kernel upgrades underneath Squid. --- diff --git a/src/cache_cf.cc b/src/cache_cf.cc index 2689d2f0a2..d0a967434d 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -3090,6 +3090,11 @@ parse_http_port_option(http_port_list * s, char *token) debugs(3, DBG_IMPORTANT, "Starting IP Spoofing on port " << s->s); debugs(3, DBG_IMPORTANT, "Disabling Authentication on port " << s->s << " (IP spoofing enabled)"); + if (!IpInterceptor.ProbeForTproxy(s->s)) { + debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: TPROXY support in the system does not work."); + self_destruct(); + } + } else if (strcmp(token, "ipv4") == 0) { #if USE_IPV6 if ( !s->s.SetIPv4() ) { diff --git a/src/ip/IpIntercept.cc b/src/ip/IpIntercept.cc index cdb8f01c34..db828ef0a5 100644 --- a/src/ip/IpIntercept.cc +++ b/src/ip/IpIntercept.cc @@ -438,3 +438,85 @@ IpIntercept::SetTproxy2OutgoingAddr(int fd, const IpAddress &src) return 0; } #endif + +bool +IpIntercept::ProbeForTproxy(IpAddress &test) +{ + debugs(3, 3, "Detect TPROXY support on port " << test); +#if LINUX_TPROXY2 + +#if USE_IPV6 + /* TPROXYv2 is not IPv6 capable. Force wildcard sockets to IPv4. Die on IPv6 IPs */ + debugs(3, DBG_IMPORTANT, "Disabling IPv6 on port " << test << " (TPROXYv2 interception enabled)"); + if ( test.IsIPv6() && !test.SetIPv4() ) { + debugs(3, DBG_CRITICAL, "IPv6 requires TPROXYv4 support. You only have TPROXYv2 for " << test ); + return false; + } +#endif /* USE_IPV6 */ + return true; + +#else /* not LINUX_TPROXY2 */ + +#if defined(IP_TRANSPARENT) + + int tos = 1; + int tmp_sock = -1; + +#if USE_IPV6 + /* Probe to see if the Kernel TPROXY support is IPv6-enabled */ + if (test.IsIPv6()) { + debugs(3, 3, "...Probing for IPv6 TPROXY support."); + + struct sockaddr_in6 tmp_ip6; + IpAddress tmp = "::2"; + tmp.SetPort(0); + tmp.GetSockAddr(tmp_ip6); + + if ( (tmp_sock = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP)) >= 0 && + setsockopt(tmp_sock, SOL_IP, IP_TRANSPARENT, (char *)&tos, sizeof(int)) == 0 && + bind(tmp_sock, (struct sockaddr*)&tmp_ip6, sizeof(struct sockaddr_in6)) == 0 ) { + + debugs(3, 3, "IPv6 TPROXY support detected. Using."); + shutdown(tmp_sock, SHUT_RDWR); + return true; + } + if (tmp_sock >= 0) { + shutdown(tmp_sock, SHUT_RDWR); + tmp_sock = -1; + } + } + + if ( test.IsIPv6() && !test.SetIPv4() ) { + debugs(3, DBG_CRITICAL, "TPROXY lacks IPv6 support for " << test ); + return false; + } +#endif + + /* Probe to see if the Kernel TPROXY support is IPv4-enabled (aka present) */ + if (test.IsIPv4()) { + debugs(3, 3, "...Probing for IPv4 TPROXY support."); + + struct sockaddr_in tmp_ip4; + IpAddress tmp = "127.0.0.2"; + tmp.SetPort(0); + tmp.GetSockAddr(tmp_ip4); + + if ( (tmp_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) >= 0 && + setsockopt(tmp_sock, SOL_IP, IP_TRANSPARENT, (char *)&tos, sizeof(int)) == 0 && + bind(tmp_sock, (struct sockaddr*)&tmp_ip4, sizeof(struct sockaddr_in)) == 0 ) { + + debugs(3, 3, "IPv4 TPROXY support detected. Using."); + shutdown(tmp_sock, SHUT_RDWR); + return true; + } + if (tmp_sock >= 0) { + shutdown(tmp_sock, SHUT_RDWR); + } + } + +#else /* undefined IP_TRANSPARENT */ + debugs(3, 3, "setsockopt(IP_TRANSPARENT) not supported on this platform. Disabling TPROXYv4."); +#endif +#endif /* LINUX_TPROXY2 */ + return false; +} diff --git a/src/ip/IpIntercept.h b/src/ip/IpIntercept.h index 3dfff4b7b6..ae46a4b2ec 100644 --- a/src/ip/IpIntercept.h +++ b/src/ip/IpIntercept.h @@ -23,7 +23,7 @@ class IpAddress; class IpIntercept { public: - IpIntercept() : transparent_active(0), intercept_active(0), last_reported(0) {}; + IpIntercept() : transparent_active(0), intercept_active(0), last_reported(0), tproxy_version(TPROXY_UNKNOWN) {}; ~IpIntercept() {}; /** Perform NAT lookups */ @@ -35,6 +35,17 @@ public: int SetTproxy2OutgoingAddr(int fd, const IpAddress &src); #endif + /** + * Test system networking calls for TPROXY support. + * Detects IPv6 and IPv4 level of support matches the address being listened on + * and if the compiled v2/v4 is usable as far down as a bind()ing. + * + * \param test Address set on the http(s)_port being checked. + * \retval true TPROXY is available. + * \retval false TPROXY is not available. + */ + bool ProbeForTproxy(IpAddress &test); + /** \retval 0 Full transparency is disabled. \retval 1 Full transparency is enabled and active.