Nmap Development mailing list archives
Re: Dual Listening on IPV4 & 6 in broker and listen modes
From: David Fifield <david () bamsoftware com>
Date: Thu, 23 Jun 2011 23:41:22 -0700
On Wed, Jun 22, 2011 at 04:58:43PM -0500, Colin L. Rice wrote:
Hello, At the request of David I rewrote broker to allow clients using IPV4 and IPV6 to communicate with each other using the default broker as well as rewriting the whole dual listening system to make a little more sense and be more maintainable. However due to a weird feature of Linux where :: binds to 0.0.0.0 as well we added a change where all IPV6 sockets now specify IPV6_V6ONLY so on Linux networking stacks you can have a dual listening mode without collisions. This means however that ncat -l -6 :: will not accept IPV4 connections in their IPV6 address format on Linux.
This isn't a feature of Linux only, it's part of the design of IPv6 sockets. See sections 3.7 "Compatibility with IPv4 Nodes" and 5.3 "IPV6_V6ONLY option for AF_INET6 Sockets" of RFC 3493. http://tools.ietf.org/html/rfc3493 Some operating systems disable the "compatibility" part by default for technical or security reasons. http://tools.ietf.org/html/draft-itojun-v6ops-v4mapped-harmful-02
The patch is attached. Does anyone have any feedback? Would you prefer that IPV6_V6ONLY only be set for ncat -l or ncat --broker and it be turned off -6 is passed?
I think that -6 mode should not accept any IPv4 connections, not even from IPv4-mapped addresses like ::ffff:127.0.0.1. If I run "ncat -6 -l 80" I expect to also be able to run a separate IPv4 web server. I think we should turn on IPV6_V6ONLY for all IPv6 sockets.
Index: ncat_listen.c =================================================================== --- ncat_listen.c (revision 24247) +++ ncat_listen.c (working copy) /* setup the main listening socket */ - listen_socket = do_listen(SOCK_STREAM, proto, &srcaddr); + listen_socket = do_listen(SOCK_STREAM, proto, &srcaddr[0]);
I think that wherever you refer to srcaddr[0], you need to refer to srcaddr[1] equally. They should not be separated in the code. The best way is to loop over num_srcaddrs. listen_socket should be an array of the same size as srcaddr, not separate variables listen_socket and listen_socket6.
@@ -545,7 +535,7 @@ while (1) { /* create the UDP listen socket */ - sockfd = do_listen(SOCK_DGRAM, proto, &srcaddr); + sockfd = do_listen(SOCK_DGRAM, proto, &srcaddr[0]);
This looks broken to me. The UDP mode only refers to srcaddr[0].
Index: ncat_main.c =================================================================== --- ncat_main.c (revision 24247) +++ ncat_main.c (working copy) @@ -533,6 +533,7 @@ if (o.verbose) print_banner(); + if(o.debug) nbase_set_log(loguser, logdebug); else @@ -541,7 +542,7 @@ /* Will be AF_INET or AF_INET6 when valid */ memset(&targetss.storage, 0, sizeof(targetss.storage)); targetss.storage.ss_family = AF_UNSPEC; - httpconnect.storage = socksconnect.storage = srcaddr.storage = targetss.storage; + httpconnect.storage = socksconnect.storage = srcaddr[0].storage = srcaddr[1].storage = targetss.storage;
I would prefer that you handle these things in a loop, instead of hardcoding 0 and 1.
if (proxyaddr) { if (!o.proxytype) @@ -582,7 +583,7 @@ if (o.listen) bye("-l and -s are incompatible. Specify the address and port to bind to like you would a host to connect to."); - if (!resolve(source, 0, &srcaddr.storage, &srcaddrlen, o.af)) + if (!resolve(source, 0, &srcaddr[0].storage, &srcaddrlen[0], o.af)) bye("Could not resolve source address %s.", source); } @@ -592,18 +593,18 @@ compatibility. */ o.portno = srcport; } else { - if (srcaddr.storage.ss_family == AF_UNSPEC) - srcaddr.storage.ss_family = o.af; + if (srcaddr[0].storage.ss_family == AF_UNSPEC) + srcaddr[0].storage.ss_family = o.af; if (o.af == AF_INET) { - srcaddr.in.sin_port = htons((unsigned short) srcport); - if (!srcaddrlen) - srcaddrlen = sizeof(srcaddr.in); + srcaddr[0].in.sin_port = htons((unsigned short) srcport); + if (!srcaddrlen[0]) + srcaddrlen[0] = sizeof(srcaddr[0].in); } #ifdef HAVE_IPV6 else { - srcaddr.in6.sin6_port = htons((unsigned short) srcport); - if (!srcaddrlen) - srcaddrlen = sizeof(srcaddr.in6); + srcaddr[0].in6.sin6_port = htons((unsigned short) srcport); + if (!srcaddrlen[0]) + srcaddrlen[0] = sizeof(srcaddr[0].in6); } #endif } @@ -626,6 +627,7 @@ if (!resolve(o.target, 0, &targetss.storage, &targetsslen, o.af)) bye("Could not resolve hostname %s.", o.target); optind++; + o.inetset=1;
I think you can make this code a lot clearer. Instead of overloading the meaning of the global srcaddr array (used for both option processing and as data passed to ncat_listen), use a temporary variable for option processing only. Then after the option loop, it can be very clear: num_srcaddrs = 0; if (tmp_addr.storage.ss_family == AF_UNSPEC) { if (o.af == AF_INET || o.af == AF_UNSPEC) srcaddr[num_srcaddrs++] = 0.0.0.0; if (o.af == AF_INET6 || o.af == AF_UNSPEC) srcaddr[num_srcaddrs++] = ::; } else { srcaddr[num_srcaddrs++] = tmp_addr; } I think that better shows your intention of setting up two listening addresses when no address and neither -4 nor -6 is given. This means that you will have to change the default value of o.af in listen mode; I think that's cleaner than the o.inetset variable. This also can clear up a lot of confusion when someone is reading the option processing loop while thinking about connect mode: "Why are they using an array when you can only connect to one address?"
Index: ncat_core.c =================================================================== --- ncat_core.c (revision 24247) +++ ncat_core.c (working copy) @@ -107,8 +107,8 @@ #include <time.h> #include <assert.h> -union sockaddr_u srcaddr; -size_t srcaddrlen; +union sockaddr_u srcaddr[2]; +size_t srcaddrlen[2];
Do we need srcaddrlen? Could we get rid of it? This declaration needs a comment saying why the array has size 2: we set up at most 2 listening sockets, one for IPv4 and one for IPv6. David Fifield _______________________________________________ Sent through the nmap-dev mailing list http://cgi.insecure.org/mailman/listinfo/nmap-dev Archived at http://seclists.org/nmap-dev/
Current thread:
- Dual Listening on IPV4 & 6 in broker and listen modes Colin L. Rice (Jun 22)
- Re: Dual Listening on IPV4 & 6 in broker and listen modes David Fifield (Jun 23)
- Re: Dual Listening on IPV4 & 6 in broker and listen modes David Fifield (Jun 24)
- Re: Dual Listening on IPV4 & 6 in broker and listen modes David Fifield (Jun 23)