Update on Port Scanner Challenge
The other day I posted the Port Scanner Challenge, and a follow-up article declaring a winner.
This lead to a couple of things...
First, Robert E. Lee (who is associated with UnicornScan) started a blog to perform his own independent tests. I encourage everyone to look at the results... but I remind everyone that Robert is tied to UnicornScan and therefore you may have to take some of the results with a grain of salt.
Second, Fabian, of Recurity Labs (Author's of PortBunny), contacted me regarding the results I had seen, specifically the Vista results. They had reproduced the results in their lab, and ended up releases an update to PortBunny. The updated version showed significant improvements. On the Vista host, with default settings, PortBunny scan times were reduced from ~18.3 seconds to ~1.2 seconds, and on a full port scan (1-65535), scan times were reduced from ~642.5 seconds to ~30 seconds. The updated version of PortBunny can be downloaded here.
Additionally, Fabian included an explanation of how packet retransmission works with PortBunny, which I found rather interesting:
PortBunny sends so called packet-batches which consist of a couple of
probes (usually 9) and a trigger-packet. If a trigger-drop is detected
either because a timeout-clock is hit or due to the fact that 3 later
trigger-responses have been received, all probes which did not get
responses are retransmitted. This is done to acknowledge that, when
firing at this rate, the trigger dropped, so its possible that any other
packet of the batch may have dropped as well.However, retransmission is not done straight away: That wouldn't be too
wise because the response may just be a couple of milliseconds away.Instead, we just add the port to the back of the list of ports to scan.
As a result, we can wait the maximum amount of time for the response to
still reach us before we resend.We only assume that a port is filtered if no response is received for
the probe but the trigger-response for the batch the probe was in was
received.Now, we do this until all ports have results and then we check whether
the total amount of filtered ports is smaller than 30% of the total
number of ports. If this is so, we perform two rounds of rescanning of
the filtered ports.
Lastly, Fabian also included some of the more interesting changes in this updated version of PortBunny:
(1) The Python-UI contained a Bug which drastically decreased
performance on gigabit-ethernet: To query the device-file, a python
FileObject was used and its read-method was called without specifying a
buffer-size. In fast networks (such as gigabit-ethernet) this lead to
the situation were a huge amount of results was delivered to userspace
in a single read. The information was then parsed using a regular
expression which, due to the size of the buffer, took way longer to
complete than the actual scan![]()
(2) The development-version now discards bad triggers as soon as better
ones are found. This means that ICMP or UDP-triggers as well as
TCP-SYN-triggers which produce TCP-SYN-ACK responses are discarded as
soon as a single closed port is found (in which case we can use this
port for triggering). This increases performance on the one hand (when
ICMP-traffic is limited which is quite frequently the case for
destination-unreachable messages) and accuracy on the other hand because
triggers are preferred by the scanner which are handled just like the
probes so rate-limitations on TCP-SYNs are detected correctly.(3) Scans were too "bursty" for many setups which included
burst-limitations. Especially when the round-trip-time was small, the
target would feel like it was processing an (almost) never ending burst
of data. We've made some changes to reduce the "burstiness" as you can
see in the Vista example.(4) TCP-Reno was taken a little to literally: Reno says that the initial
congestion threshold should be close to infinity so that the sender can
find the limitations of the network quickly (and "muscle" itself into
the connection). NMAP chooses 50 as an initial congestion threshold,
PortBunny chose 80000. While 80000 was closer to infinity than 50, it
doesn't seem like a good choice in many environments when using Reno for
port-scanning because the accuracy of the start-phase of the scan is
reduced drastically. NMAP was totally right to choose a lower number so
we've changed that as well.(5) We've included a new trigger: The TCP-ACK trigger. This works in
many situations where we had to use fallback-triggers such as the
UDP-trigger in the past.
