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;
+}
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 */
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.