Nmap Development mailing list archives
Tudor's Status Report - #9 of #17
From: Tudor-Emil COMAN <tudor_emil.coman () cti pub ro>
Date: Mon, 4 Jul 2016 22:52:39 +0000
Hello, I spent the past week finishing up and polishing the IOCP engine for Nsock. I've made a branch in my directory in nmap-exp: https://svn.nmap.org/nmap-exp/tudor/nsock-iocp/ Brandon has advised me watch out for and test some key particular cases. SSL: In order to test SSL I used the following command: # nmap.exe -p 443 -v -d -Pn -n -T5 --script=ssl-cert www.citibank.com --nsock-engine=iocp And it works the same as the other engines. UDP: There was a problem with UDP from the ConnectEx function. The DNS reverse lookup wasn't working and after pinpointing that the problem was with ConnectEx I went back to the documentation and found that:
The ConnectEx function is only supported on connection-oriented sockets.
After seeing that, I went back and used the lastproto member of the niod structure to decide whether to use connect(if lastproto is not IPPROTO_TCP) or ConnectEx otherwise. This seems to have solved the DNS reverse lookup problem. IPv6 scanning seems to work. PPP fails with:
Only ethernet devices can be used for raw scans on Windows, and "ppp0" is not an ethernet device. Use the --unprivileged option'
This is probably from a safeguard somewhere but I didn't have time to search for it and disable it. Localhost scanning shows all ports marked as unknown. One of the concerns regarding adding another engine was that it would add more complexity to Nsock in general and make the code more hard to read. There was quite a bit of code that was pilling up in nsock_core.c so I took all that code from there and added it to a new file that I named nsock_iocp.c with a nsock_iocp.h to be included by other files.
From nsock_core only 3 functions are called from that file:
initiate_overlapped_event() (2 times) terminate_overlapped_event() (1 time) get_overlapped_result() (3 times) - initiate_overlapped_event() needs to be called every single time an event needs to perform an action on a socket. So it is called both when an event is associated with a socket and when the event was processed but not finished. - terminate_overlapped_event() needs to be called when the event associated with the overlapped operation has expired. - get_overlapped_result() has to be called to get the results of the previously initiated overlapped event. This will replace the send and recv functions from the read and write handlers but it will also be called from the connect handler to get the error (if an error has occurred). Two lists were also added in the npool structure to keep track of the extended_overlapped buffers and recycle them in the same way nevents and niods recycled. One big problem engine IOCP has is that it uses a lot of memory. Not only because one special structure needs to be made for each little read/write/connect that happens, for the read event, a read buffer 8192 bytes in size(to mirror the one in do_actual_read) has to be allocated and kept for each read operation at one moment in time. Even though it happened rarely and in extreme testing conditions (parallelism level > 2000, hostgroup > 5000) I did loose some scans because Nmap would run out of memory and exit. In nsock_iocp.h there is also a free_eov exposed that is used by engine_iocp.c So that's about the extent of the added complexity. One more important thing is that in nbase_misc the socket is created with the WSA_FLAG_OVERLAPPED which is rather harmless because such a socket supports non-overlapped operations just as well, it just *enables* overlapped. Even the Microsoft documentations states that:
Most sockets should be created with this flag set.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms742212(v=vs.85).aspx HAVE_IOCP is defined always alongside HAVE_POLL. The official Microsoft documentation says that most of the function calls that I used like ConnectEx, GetQueuedCompletionStatusEx, WSARecv are only available after Vista. Some people said that these functions can be found Windows XP too and they probably are but I don't think it's a good idea to use them especially if we drop support for Windows XP anyway. Also I gave the engine a lower priority than poll so it should be called explicitly with the --nsock-engine=iocp parameter. I also added another engine comparison. Last week's scans were bad because I didn't handle the expired events well but now that's fixed and the results make more sense. For the scans in these graphs I also disabled NSE for service scanning. I also took a peek into those old registry tweaks. - MaxUserPort: https://support.microsoft.com/en-us/kb/196271 So the problem with this one as I understood it was that if a connect would bind the local address to a source port higher than 5000, it would fail with WSAENOBUFS. It's fairly simple to test out, just before issuing the connect() call I bind that socket on ports higher that 5000. I use a static variable in connect_internal that starts at 5000, the value is used to bind the socket and it is then incremented for the next call. I tested it on Windows Vista Ultimate 64-bit(in a VM) and Windows 7 Professional 32-bit(in a VM) with a service scan and the bind never failed. Nmap was compiled from source so those registry tweaks weren't issued by the installer or anything. - TcpTimedWaitDelay: https://support.microsoft.com/en-us/kb/149532 I don't really see the problem here to be honest. You get less active connections than your port range because some of those ports will be caught up in the TimeWait state after a TCP connection ended. The TcpTimedWaitDelay default value is 240 seconds and we reduce the amount of time we have to wait for these ports to linger to 30 seconds so it is better in a way to have this. - StrictTimeWaitSeqCheck needs to be set to 1 in order for TcpTimedWaitDelay to take effect. The MaxUserPort entry increases the default range of the ports used for outgoing connections all the way up from 5000 to 65534 thus removing a pointless connection cap. I don't think we should remove these registry entries. Accomplishments: - Switched from GetQueuedCompletionStatus to GetQueuedCompletionStatusEx and identified and fixed a bug with the latter function. - Added lists to the pool structure that should track the usage of extended_overlapped structures to make sure no memory leaks occur and also recycle what it can for future use. - Finally made a SVN branch. - Restructured the code, moved a lot of it into separate files. - Investigated the registry tweaks. Priorities: - See what could be improved. - Take another look at the tftp-enum script. - Make some really cool engine_iocp stats. Any thoughts? Tudor
_______________________________________________ Sent through the dev mailing list https://nmap.org/mailman/listinfo/dev Archived at http://seclists.org/nmap-dev/
Current thread:
- Tudor's Status Report - #9 of #17 Tudor-Emil COMAN (Jul 04)
- Re: Tudor's Status Report - #9 of #17 Fyodor (Jul 13)