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)
