Debian – ICMP : Port unreachable error even if port is open

debianicmpnmapSecuritytcp/ip

I am testing my Debian Server with some Nmap port Scanning. My Debian is a Virtual Machine running on a bridged connection.

Classic port scanning using TCP SYN request works fine and detects port 80 as open (which is correct) :

nmap -p 80 192.168.1.166   

Starting Nmap 6.47 ( http://nmap.org ) at 2016-02-10 21:36 CET
Nmap scan report for 192.168.1.166
Host is up (0.00014s latency).
PORT   STATE SERVICE
80/tcp open  http
MAC Address: xx:xx:xx:xx:xx:xx (Cadmus Computer Systems)

Nmap done: 1 IP address (1 host up) scanned in 0.51 seconds

But when running UDP port scan, it fails and my Debian server answers with an ICMP : Port unreachable error :

nmap -sU -p 80 192.168.1.166

Starting Nmap 6.47 ( http://nmap.org ) at 2016-02-10 21:39 CET
Nmap scan report for 192.168.1.166
Host is up (0.00030s latency).
PORT   STATE  SERVICE
80/udp closed http
MAC Address: xx:xx:xx:xx:xx:xx (Cadmus Computer Systems)

Nmap done: 1 IP address (1 host up) scanned in 0.52 seconds

Wireshark record :

wireshark record


How is that possible ? My port 80 is open, how come that Debian answers with an ICMP : Port unreachable error ? Is that a security issue?

Best Answer

Albeit TCP and UDP are part of TCP/IP, both belong to the same TCP/IP or OSI layers, and both are a layer above IP, they are different protocols.

http://www.cyberciti.biz/faq/key-differences-between-tcp-and-udp-protocols/

Transmission Control Protocol (TCP) and User Datagram Protocol (UDP) are two of the core protocols of the Internet Protocol suite. Both TCP and UDP work at the transport layer TCP/IP model and both have a very different usage. TCP is a connection-oriented protocol. UDP is a connectionless protocol.

tcp ip model
(source: ml-ip.com)

Some services do indeed answer to TCP and UDP ports at the same time, as is the case of DNS and NTP services, however that is not certainly the case with web servers, which normally only answer by default to port 80/TCP (and do not work/listen at all in UDP)

You can list your UDP listenning ports in a linux system with:

$sudo netstat -anlpu
Active Internet connections (servers and established)  
Proto Recv-Q Send-Q Local Address           Foreign Address             State       PID/Program name  
udp        0      0 0.0.0.0:1900            0.0.0.0:*                           15760/minidlnad   
udp        0      0 0.0.0.0:5000            0.0.0.0:*                           32138/asterisk  
udp        0      0 0.0.0.0:4500            0.0.0.0:*                           1592/charon     
udp        0      0 0.0.0.0:4520            0.0.0.0:*                           32138/asterisk  
udp        0      0 0.0.0.0:5060            0.0.0.0:*                           32138/asterisk  
udp        0      0 0.0.0.0:4569            0.0.0.0:*                           32138/asterisk  
udp        0      0 0.0.0.0:500             0.0.0.0:*                           1592/charon     
udp        0      0 192.168.201.1:53        0.0.0.0:*                           30868/named     
udp        0      0 127.0.0.1:53            0.0.0.0:*                           30868/named     
udp        0      0 0.0.0.0:67              0.0.0.0:*                           2055/dhcpd      
udp        0      0 0.0.0.0:14403           0.0.0.0:*                           1041/dhclient   
udp    17920      0 0.0.0.0:68              0.0.0.0:*                           1592/charon     
udp        0      0 0.0.0.0:68              0.0.0.0:*                           1041/dhclient   
udp        0      0 0.0.0.0:56417           0.0.0.0:*                           2055/dhcpd      
udp        0      0 192.168.201.1:123       0.0.0.0:*                           1859/ntpd       
udp        0      0 127.0.0.1:123           0.0.0.0:*                           1859/ntpd       
udp        0      0 192.168.201.255:137     0.0.0.0:*                           1777/nmbd       
udp        0      0 192.168.201.1:137       0.0.0.0:*                           1777/nmbd       
udp        0      0 0.0.0.0:137             0.0.0.0:*                           1777/nmbd       
udp        0      0 192.168.201.255:138     0.0.0.0:*                           1777/nmbd       
udp        0      0 192.168.201.1:138       0.0.0.0:*                           1777/nmbd       
udp        0      0 0.0.0.0:138             0.0.0.0:*                           1777/nmbd       
udp        0      0 192.168.201.1:17566     0.0.0.0:*                           15760/minidlnad 

And your listening TCP ports with the command:

$sudo netstat -anlpt
Active Internet connections (servers and established)  
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name  
tcp        0      0 0.0.0.0:5060            0.0.0.0:*               LISTEN      32138/asterisk  
tcp        0      0 192.168.201.1:8200      0.0.0.0:*               LISTEN      15760/minidlnad   
tcp        0      0 192.168.201.1:139       0.0.0.0:*               LISTEN      2092/smbd       
tcp        0      0 0.0.0.0:2000            0.0.0.0:*               LISTEN      32138/asterisk  
tcp        0      0 192.168.201.1:80        0.0.0.0:*               LISTEN      7781/nginx      
tcp        0      0 192.168.201.1:53        0.0.0.0:*               LISTEN      30868/named     
tcp        0      0 127.0.0.1:53            0.0.0.0:*               LISTEN      30868/named     
tcp        0      0 192.168.201.1:22        0.0.0.0:*               LISTEN      2023/sshd       
tcp        0      0 0.0.0.0:8888            0.0.0.0:*               LISTEN      1919/perl       
tcp        0      0 127.0.0.1:953           0.0.0.0:*               LISTEN      30868/named     
tcp        0      0 192.168.201.1:445       0.0.0.0:*               LISTEN      2092/smbd       
tcp        0    224 192.168.201.1:22        192.168.201.12:56820    ESTABLISHED 16523/sshd: rui [pr

Now normally NMAP does send a SYN to the port being scanned, and per the TCP protocol, if a daemon/service is bound to the port, it will answer with a SYN+ACK, and nmap will show it as open.

TCP/IP connection negotiation: 3 way handshake

To establish a connection, TCP uses a three-way handshake. Before a client attempts to connect with a server, the server must first bind to and listen at a port to open it up for connections: this is called a passive open. Once the passive open is established, a client may initiate an active open. To establish a connection, the three-way (or 3-step) handshake occurs:

SYN: The active open is performed by the client sending a SYN to the server. The client sets the segment's sequence number to a random value A. SYN-ACK: In response, the server replies with a SYN-ACK.

3 way handshake

However, if a service is not running there, TCP/IP defines the kernel will send an ICMP message back with an "Port unreachable" message for UDP services, and TCP RST messages for TCP services.

ICMP Destination unreachable

Destination unreachable is generated by the host or its inbound gateway[3] to inform the client that the destination is unreachable for some reason. A Destination Unreachable message may be generated as a result of a TCP, UDP or another ICMP transmission. Unreachable TCP ports notably respond with TCP RST rather than a Destination Unreachable type 3 as might be expected.

So indeed, your UDP scanning to port 80/UDP simply receives an ICMP unreachable message back because there is not a service listening to that combination or protocol/port.

As for security considerations, those ICMP destination unreachable messages can certainly be blocked, if you define firewall/iptables rules that DROP all messages by default, and only allow in the ports that your machine serves to the outside. That way, nmap scans to all the open ports, especially in a network, will be slower, and the servers will use less resources.

As an additional advantage, if a daemon/service opens additional ports, or a new service is added by mistake, it won't be serving requests until it is expressly allowed by new firewall rules.

Please do note, that if instead of using DROP in iptables, you use REJECT rules, the kernel won't ignore the scanning/ TCP/IP negotiation tries, and will answer with ICMP messages of Destination unreachable, code 13: "Communication administratively prohibited (administrative filtering prevents packet from being forwarded)".

Block all ports except SSH/HTTP in ipchains and iptables

Related Question