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,6 +128,9 @@ 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;
static int ip6_transp_working = 1;
switch (local->ss_family) {
case AF_INET:
if (flags && ip_transp_working) { if (flags && ip_transp_working) {
if (setsockopt(fd, SOL_IP, IP_TRANSPARENT, &one, sizeof(one)) == 0 if (setsockopt(fd, SOL_IP, IP_TRANSPARENT, &one, sizeof(one)) == 0
|| setsockopt(fd, SOL_IP, IP_FREEBIND, &one, sizeof(one)) == 0) || setsockopt(fd, SOL_IP, IP_FREEBIND, &one, sizeof(one)) == 0)
@ -135,6 +138,16 @@ int tcp_bind_socket(int fd, int flags, struct sockaddr_storage *local, struct so
else else
ip_transp_working = 0; 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) {
memset(&bind_addr, 0, sizeof(bind_addr)); memset(&bind_addr, 0, sizeof(bind_addr));
@ -736,12 +749,23 @@ 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) {
case AF_INET:
if ((setsockopt(fd, SOL_IP, IP_TRANSPARENT, &one, sizeof(one)) == -1)
&& (setsockopt(fd, SOL_IP, IP_FREEBIND, &one, sizeof(one)) == -1)) { && (setsockopt(fd, SOL_IP, IP_FREEBIND, &one, sizeof(one)) == -1)) {
msg = "cannot make listening socket transparent"; msg = "cannot make listening socket transparent";
err |= ERR_ALERT; 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
/* Note: this might fail if not CAP_NET_RAW */ /* Note: this might fail if not CAP_NET_RAW */