]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Auto-detect the amount of TPROXY support available.
authorAmos Jeffries <squid3@treenet.co.nz>
Tue, 15 Sep 2009 11:59:51 +0000 (23:59 +1200)
committerAmos Jeffries <squid3@treenet.co.nz>
Tue, 15 Sep 2009 11:59:51 +0000 (23:59 +1200)
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.

src/cache_cf.cc
src/ip/IpIntercept.cc
src/ip/IpIntercept.h

index 2689d2f0a21fd3036919f0a439eca85eda992229..d0a967434debc672333663d41c43e96932283242 100644 (file)
@@ -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() ) {
index cdb8f01c346ed02619a529ee67dd83742a854c0b..db828ef0a5b51382522683ffc713f9405b10160e 100644 (file)
@@ -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;
+}
index 3dfff4b7b67e57a6d237b89cbe7b5d1dc8d887c2..ae46a4b2ec3f533c90b8af7785bfca00912c0a1f 100644 (file)
@@ -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.