UDP ICMP port unreachable scanning : This
scanning method varies from the above in that we are using the UDP
protocol instead of TCP. While this protocol is simpler, scanning it
is actually significantly more difficult. This is because open ports
don't have to send an acknowledgement in response to our probe, and
closed ports aren't even required to send an error packet.
Fortunately, most hosts do send an ICMP_PORT_UNREACH error when you
send a packet to a closed UDP port. Thus you can find out if a port
is NOT open, and by exclusion determine which ports which are.
Neither UDP packets, nor the ICMP errors are guaranteed to arrive, so
UDP scanners of this sort must also implement retransmission of
packets that appear to be lost (or you will get a bunch of false
positives). Also, this scanning technique is slow because of
compensation for machines that took RFC 1812 section 4.3.2.8 to heart
and limit ICMP error message rate. For example, the Linux kernel (in
net/ipv4/icmp.h) limits destination unreachable message generation to
80 per 4 seconds, with a 1/4 second penalty if that is exceeded. At
some point I will add a better algorithm to nmap for detecting this.
Also, you will need to be root for access to the raw ICMP socket
necessary for reading the port unreachable. The -u (UDP) option of
nmap implements this scanning method for root users.
Some people think UDP scanning is lame and pointless. I usually
remind them of the recent Solaris rcpbind hole. Rpcbind can be found
hiding on an undocumented UDP port somewhere above 32770. So it
doesn't matter that 111 is blocked by the firewall. But can you find
which of the more than 30,000 high ports it is listening on? With a
UDP scanner you can!
UDP recvfrom() and write() scanning : While
non-root users can't read port unreachable errors directly, Linux is
cool enough to inform the user indirectly when they have been
received. For example a second write() call to a closed port will
usually fail. A lot of scanners such as netcat and Pluvius' pscan.c
does this. I have also noticed that recvfrom() on non-blocking UDP
sockets usually return EAGAIN ("Try Again", errno 13) if the ICMP
error hasn't been received, and ECONNREFUSED ("Connection refused",
errno 111) if it has. This is the technique used for determining open
ports when non-root users use -u (UDP). Root users can also use the
-l (lamer UDP scan) options to force this, but it is a really dumb
idea.
ICMP echo scanning : This isn't really port
scanning, since ICMP doesn't have a port abstraction. But it is
sometimes useful to determine what hosts in a network are up by
pinging them all. the -P option does this. ICMP scanning is now in
parallel, so it can be quite fast. To speed things up even more, you
can increase the number of pings in parallel with the '-L '
option. It can also be helpful to tweek the ping timeout value with
'-T '. nmap supports a host/bitmask notation to make
this sort of thing easier. For example 'nmap -P cert.org/24
152.148.0.0/16' would scan CERT's class C network and whatever class B
entity 152.148.* represents. Host/26 is useful for 6-bit subnets
within an organization. Nmap now also offers a more powerful form.
You can now do things like '150.12,17,71-79.7.*' and it will do what
you expect. For each of the four values, you can either put a single
number, a range (with '-'), a comma-separated list of numbers and
ranges, or a '*' which is just a short cut for 0-255. By default,
likely network/broadcast addresses like .0 and .255 are not scanned,
but the '-A' option allows you to do this if you wish.