mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-25 14:12:13 +00:00
BUG/MEDIUM: tcp: don't use SO_ORIGINAL_DST on non-AF_INET sockets
There's an issue when using SO_ORIGINAL_DST to retrieve the original destination of a connection's address before being translated by Netfilter's DNAT/REDIRECT or the old TPROXY. SO_ORIGINAL_DST is able to retrieve an IPv4 address when the original destination was IPv4 mapped into IPv6. At first glance it's not a big deal, but it is for logging and for the proxy protocol, because we then have two different address families for the source and destination. In this case, the proxy protocol correctly detects the issue and emits "UNKNOWN". In order to fix this, we perform getsockname() first, and only if the address family is AF_INET, then we perform the getsockopt() call. This fix must be backported to 1.5, and probably even to 1.4 and 1.3.
This commit is contained in:
parent
43e7958def
commit
5e0d0e046a
@ -555,12 +555,24 @@ int tcp_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir)
|
||||
{
|
||||
if (dir)
|
||||
return getpeername(fd, sa, &salen);
|
||||
else {
|
||||
int ret = getsockname(fd, sa, &salen);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
#if defined(TPROXY) && defined(SO_ORIGINAL_DST)
|
||||
else if (getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, sa, &salen) == 0)
|
||||
return 0;
|
||||
/* For TPROXY and Netfilter's NAT, we can retrieve the original
|
||||
* IPv4 address before DNAT/REDIRECT. We must not do that with
|
||||
* other families because v6-mapped IPv4 addresses are still
|
||||
* reported as v4.
|
||||
*/
|
||||
if (((struct sockaddr_storage *)sa)->ss_family == AF_INET
|
||||
&& getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, sa, &salen) == 0)
|
||||
return 0;
|
||||
#endif
|
||||
else
|
||||
return getsockname(fd, sa, &salen);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tries to drain any pending incoming data from the socket to reach the
|
||||
|
Loading…
Reference in New Issue
Block a user