mailing list archives
Re: Spurious port closed bug.
From: James Rogers <jamesmrogers () gmail com>
Date: Mon, 18 Jun 2012 15:56:10 -0400
On Wed, Jun 13, 2012 at 3:27 PM, James Rogers <jamesmrogers () gmail com> wrote:
When a scan of this form is sent
sudo ./nmap -n -p 80 nmap.org --packet-trace
it almost always comes back like this:
SENT (0.2146s) TCP 192.168.5.96:62799 > 22.214.171.124:443 S ttl=57
id=26684 iplen=44 seq=3835492086 win=1024 <mss 1460>
SENT (0.2148s) TCP 192.168.5.96:62799 > 126.96.36.199:80 A ttl=58
id=4759 iplen=40 seq=0 win=1024
SENT (0.7961s) TCP 192.168.5.96:62799 > 188.8.131.52:80 S ttl=55
id=26240 iplen=44 seq=4209866743 win=1024 <mss 1460>
RCVD (0.9954s) TCP 184.108.40.206:80 > 192.168.5.96:62799 SA ttl=52
id=0 iplen=44 seq=3953231165 win=14600 <mss 1356>
and the http is reported as open:
Host is up (0.53s latency).
PORT STATE SERVICE
80/tcp open http
(I am ignoring the ICMP packets for this to make the results clearer.)
On a good, fast network it is almost impossible to get the wrong
result. This makes trouble shooting the issue a problem. When you
can't recreate it, did you fix the issue, or did the network
congestion just get better.
But on a network that is dropping packets or delivering them out of
order it is a different story. Depending on how bad the network is you
can get a wrong result anywhere from 1 in 10 to 1 in 5 packets. The
McDonald's network was really bad this morning.
The bad results look like:
SENT (0.2067s) TCP 192.168.5.96:33389 > 220.127.116.11:443 S ttl=40
id=35821 iplen=44 seq=298682555 win=1024 <mss 1460>
SENT (0.2069s) TCP 192.168.5.96:33389 > 18.104.22.168:80 A ttl=46
id=2272 iplen=40 seq=0 win=1024
SENT (0.4014s) TCP 192.168.5.96:33389 > 22.214.171.124:80 S ttl=59
id=16598 iplen=44 seq=2367880103 win=1024 <mss 1460>
RCVD (0.4049s) TCP 126.96.36.199:80 > 192.168.5.96:33389 R ttl=52 id=0
iplen=40 seq=298682555 win=0
Host is up (0.17s latency).
PORT STATE SERVICE
80/tcp closed http
Nmap done: 1 IP address (1 host up) scanned in 0.43 seconds
Or even this:
SENT (0.2372s) TCP 192.168.5.96:49360 > 188.8.131.52:443 S ttl=49
id=50774 iplen=44 seq=3212604348 win=1024 <mss 1460>
SENT (0.2374s) TCP 192.168.5.96:49360 > 184.108.40.206:80 A ttl=40
id=24380 iplen=40 seq=0 win=1024
SENT (0.4769s) TCP 192.168.5.96:49360 > 220.127.116.11:80 S ttl=58
id=27597 iplen=44 seq=235178041 win=1024 <mss 1460>
RCVD (0.4823s) TCP 18.104.22.168:443 > 192.168.5.96:49360 SA ttl=52
id=0 iplen=44 seq=155794850 win=14600 <mss 1356>
RCVD (0.4825s) TCP 22.214.171.124:80 > 192.168.5.96:49360 R ttl=52 id=0
iplen=40 seq=3212604348 win=0
Host is up (0.20s latency).
PORT STATE SERVICE
80/tcp closed http
This is what RFC 793 says starting on page 64:
If the state is LISTEN then
second check for an ACK
Any acknowledgment is bad if it arrives on a connection still in
the LISTEN state. An acceptable reset segment should be formed
for any arriving ACK-bearing segment. The RST should be
formatted as follows:
third check for a SYN
If the SYN bit is set, check the security. If the
security/compartment on the incoming segment does not exactly
match the security/compartment in the TCB then send a reset and
If the SEG.PRC is greater than the TCB.PRC then if allowed by
the user and the system set TCB.PRC<-SEG.PRC, if not allowed
send a reset and return.
If the SEG.PRC is less than the TCB.PRC then continue.
Set RCV.NXT to SEG.SEQ+1, IRS is set to SEG.SEQ and any other
control or text should be queued for processing later. ISS
should be selected and a SYN segment sent of the form:
SND.NXT is set to ISS+1 and SND.UNA to ISS. The connection
state should be changed to SYN-RECEIVED. Note that any other
incoming control or data (combined with SYN) will be processed
in the SYN-RECEIVED state, but processing of SYN and ACK should
not be repeated. If the listen was not fully specified (i.e.,
the foreign socket was not fully specified), then the
unspecified fields should be filled in now.
If a syn comes in on a listen port, then it is supposed to send a
If an ack comes in on a listen port, then it is supposed to send rst back.
I believe that is happening is that the two packets we send to port
80, an ACK and a SYN are returning in different orders depending on
network quality/congestion. If the packets get there in SYN - ACK
order then that could really confuse the host on the other side,
especially considering how the sequence numbers are not properly
aligned for a syn, syn-ack, ack handshake.
I am noticing that we never get the receive for all three packets. and
if we get more than just the SA packet back then we think the
connection is closed.
How can I match up the returning packet to the packet that was sent?
I'm not seeing a clear way to differentiate between an RST on the A
packet and the one on the SYN packet.
The strange thing is that the seq number in the RST packet from port
80 on the other host is always equal to the sequence number in the
segment we sent to port 443. So I am really confused about which
segment this RST belongs to.
I am thinking that if I send all three packets from different ports
then I would know for sure which returning packet belonged to which
sent packet, is that a practical solution? Is there a command line
option to do that? Do we match the packets by the ACK (number - 1)?
If I put the ack number in the --packet-trace output could this help
us line the acks up to the sends better?
I was able to stop the bug from happening by incrementing the port of
the first ack in massping().
Evidently this earlier ack is sometimes triggering a reset to be sent
which we were seeing as the response to the later packet.
I traced back to where we set the default ports inside
validate_scan_lists() and instead of setting them to 443 and 80 for
the syn and ack host detection packets I set them to random values
above 32,000. Ports in these higher ranges are often allowed to
receive packets when port 80 or 443 are heavily guarded by firewall
and packet filter rules.
By randomizing these host detection ports each time we scan, we could
make nmap less predictable and harder to spot.
An alternative is to change port 80 to a random higher value if we are
tcp scanning for port 80 later. Unfortunately this information is not
available to validate_scan_lists at the time port 80 and port 443 are
being added to the ping syn and ping ack lists.
Sent through the nmap-dev mailing list
Archived at http://seclists.org/nmap-dev/