Been looking at TPROXY support in 3.1, and good news is that it seems to
mostly work.

Bad news is that it interacts badly with hosts having IPv6 addresses in
DNS, resulting in errors in cache.log + probably attempt to IPv6
connection. Similar breakage probably also exists when
tcp_outgoing_address is set to an ipv4 address.


The culpit is here


ConnectStateData::connect()

#if USE_IPV6
    case COMM_ERR_PROTOCOL:
        /* problem using the desired protocol over this socket.
         * count the connection attempt, reset the socket, and immediately try 
again */
        tries++;
        commResetFD();
        connect();
        break;
#endif

which comes from here:

comm_connect_addr(int sock, const IpAddress &address)

    /* BUG 2222 FIX: reset the FD when its found to be IPv4 in IPv6 mode */
    /* inverse case of IPv4 failing to connect on IPv6 socket is handeld 
post-connect.
     * this case must presently be handled here since the GetAddrInfo asserts 
on bad mappings.
     * eventually we want it to throw a Must() that gets handled there instead 
of this if.
     * NP: because commresetFD is private to ConnStateData we have to return an 
error and
     *     trust its handled properly.
     */
#if USE_IPV6
    if (F->sock_family == AF_INET && !address.IsIPv4()) {
        return COMM_ERR_PROTOCOL;
    }
#endif

and because of this commResetFD resets the FD to IPv6, which isn't
desired when using tproxy or tcp_outgoing_address, But fixing
commResetFD to account for this breaks the above instead (infinite
loop).

When the outgoing address is set to IPv4 then we should not be looking
for IPv6 addresses, or try to connect to IPv6 destinations.

Not sure how to best fix this without rewriting comm_connect socket
management to get rid of commResetFD.. (a change which is long overdue
btw).

Regards
Henrik


Reply via email to