MINOR: IPv6 support for transparent proxy

Set socket option IPV6_TRANSPARENT on binding
to enable transparent proxy on IPv6.
This option is available from Linux 2.6.37.
This commit is contained in:
David du Colombier 2012-07-13 14:34:59 +02:00 committed by Willy Tarreau
parent 5b88da269c
commit 65c1796c4a
2 changed files with 38 additions and 11 deletions

View File

@ -88,6 +88,9 @@
#if !defined(IP_TRANSPARENT) #if !defined(IP_TRANSPARENT)
#define IP_TRANSPARENT 19 #define IP_TRANSPARENT 19
#endif /* !IP_TRANSPARENT */ #endif /* !IP_TRANSPARENT */
#if !defined(IPV6_TRANSPARENT)
#define IPV6_TRANSPARENT 75
#endif /* !IPV6_TRANSPARENT */
#endif /* CONFIG_HAP_LINUX_TPROXY */ #endif /* CONFIG_HAP_LINUX_TPROXY */
/* We'll try to enable SO_REUSEPORT on Linux 2.4 and 2.6 if not defined. /* We'll try to enable SO_REUSEPORT on Linux 2.4 and 2.6 if not defined.

View File

@ -128,12 +128,25 @@ int tcp_bind_socket(int fd, int flags, struct sockaddr_storage *local, struct so
#ifdef CONFIG_HAP_LINUX_TPROXY #ifdef CONFIG_HAP_LINUX_TPROXY
static int ip_transp_working = 1; static int ip_transp_working = 1;
if (flags && ip_transp_working) { static int ip6_transp_working = 1;
if (setsockopt(fd, SOL_IP, IP_TRANSPARENT, &one, sizeof(one)) == 0 switch (local->ss_family) {
|| setsockopt(fd, SOL_IP, IP_FREEBIND, &one, sizeof(one)) == 0) case AF_INET:
foreign_ok = 1; if (flags && ip_transp_working) {
else if (setsockopt(fd, SOL_IP, IP_TRANSPARENT, &one, sizeof(one)) == 0
ip_transp_working = 0; || setsockopt(fd, SOL_IP, IP_FREEBIND, &one, sizeof(one)) == 0)
foreign_ok = 1;
else
ip_transp_working = 0;
}
break;
case AF_INET6:
if (flags && ip6_transp_working) {
if (setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, &one, sizeof(one)) == 0)
foreign_ok = 1;
else
ip6_transp_working = 0;
}
break;
} }
#endif #endif
if (flags) { if (flags) {
@ -736,11 +749,22 @@ int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen)
setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)); setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
#endif #endif
#ifdef CONFIG_HAP_LINUX_TPROXY #ifdef CONFIG_HAP_LINUX_TPROXY
if ((listener->options & LI_O_FOREIGN) if (listener->options & LI_O_FOREIGN) {
&& (setsockopt(fd, SOL_IP, IP_TRANSPARENT, &one, sizeof(one)) == -1) switch (listener->addr.ss_family) {
&& (setsockopt(fd, SOL_IP, IP_FREEBIND, &one, sizeof(one)) == -1)) { case AF_INET:
msg = "cannot make listening socket transparent"; if ((setsockopt(fd, SOL_IP, IP_TRANSPARENT, &one, sizeof(one)) == -1)
err |= ERR_ALERT; && (setsockopt(fd, SOL_IP, IP_FREEBIND, &one, sizeof(one)) == -1)) {
msg = "cannot make listening socket transparent";
err |= ERR_ALERT;
}
break;
case AF_INET6:
if (setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, &one, sizeof(one)) == -1) {
msg = "cannot make listening socket transparent";
err |= ERR_ALERT;
}
break;
}
} }
#endif #endif
#ifdef SO_BINDTODEVICE #ifdef SO_BINDTODEVICE