iptables - match closed ports

The previous post already discussed why it is a good thing to see connections coming in to closed ports, the approach presented was pcap with filters.

Today, we'll use iptables to detect connections to closed ports.

historics

I've had discussions with Tillmann from honeytrap some time ago about honeytrap using iptables & nfq to detect incoming connections, the problem is, honeytrap gets all incoming connections, and does not know if the connection destination port is bound, and therefore tries to bind it.
When stealing adopting the idea for nepenthes, I decided to parse /proc/net/tcp for each incoming connection, so I knew if there was a service listening on the port already, allowing to bind the service only in case there was no service bound before.

unrelated TARPIT problems

After messing with iptables yesterday …
I wanted to install netfilter-extensions -to have the TARPIT target- on a Ubuntu Hardy Unfortunately Hardy's netfilter-extensions is incompatible with the shipped kernel, as Ubuntu does not adapt netfilter-extensions to the kernel they ship, but just stick to the debian package …
Nevertheless, installing iptables_1.4.0-4ubuntu2_i386.deb for iptables userland to be able to parse TARPIT, and netfilter-extensions-source_20080719+debian-1_all.deb from debian, allowed me to install the module using module-assistant.

to the point

So, after messing with iptables yesterday, I thought about what was required to extend iptables to be able to match packet addressing closed ports.
I knew /proc/net/tcp code might provide hints where to get the list of all open connections, and had a look on netfilter/iptables code how to get things done. During my investigations, I stumbled upon somebody else asking for the same iptables capability:

>Would you happen to know a way to control system behaviour when
>connection requests are received on TCP or UDP ports where there is no
>socket listening? I know this can be done using net.inet.tcp.blackhole
>or net.inet.udp.blackhole in FreeBSD but I'm not aware of anything
>similar in Linux, so I thought iptables would be the only possibility.

-m socket, but the tproxy guys have not yet merged that code :-/

on the netfilter ml.

Cool, next thing was checking if they merged the code already, …

 Wed, 8 Oct 2008 09:35:12 +0000 (11:35 +0200)
Add iptables 'socket' match, which matches packets for which a TCP/UDP
socket lookup succeeds.

linus 2.6 tree

Cool, I wanted to use it, so I had a look into the iptables manual, and it says:

   socket
       This matches if an open socket can be found by doing a socket lookup on the packet.

current limitations

Testing the socket match, I've had some problems

  • connections which would be accepted by a “INADDR_ANY” listener (0.0.0.0) are not matched
    • there is no workaround but no to listen on 0.0.0.0
  • you are not able to match for not existing sockets
    • workaround is matching for existing sockets and ACCEPT, do whatever you want to do with not-matching sockets afterwards

it works

Using previously mentioned workarounds, here are some short instructions how to set it up to log packets which are directed to your host without having a listener specified:

iptables -t mangle -A PREROUTING -i eth0 -p tcp -m socket -j ACCEPT
iptables -t mangle -A PREROUTING -i eth0 -p tcp -j LOG

You can verify:

iptables -t mangle -vL
Chain PREROUTING (policy ACCEPT 325 packets, 52866 bytes)
 pkts bytes target     prot opt in     out     source               destination         
14350 8790K ACCEPT     tcp  --  eth0   any     anywhere             anywhere            socket 
   22 14902 LOG        tcp  --  eth0   any     anywhere             anywhere            LOG level warning 

or looking at /var/log/syslog

kernel: [1106956.819623] IN=eth0 OUT= MAC=aa:bb:cc:dd:ee:ff:gg:hh:ii:jj:kk:ll:mm:nn SRC=192.168.1.21 DST=192.168.1.20 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=38618 DF PROTO=TCP SPT=4266 DPT=4712 WINDOW=5840 RES=0x00 SYN URGP=0 

suggested improvements

Even though it works, avoiding the worksarounds would be great, so some suggestions:

  • extend the syntax for socket
    • --exists (yes|no) (default to no for compatibility)
      • allow matching for not existing listeners as well
    • --ignore-wildcard (yes|no) (default to yes for compatibility)
      • not ignoring 0.0.0.0 is useful, avoids workarounds

why it is useful

Previously we used

iptables -A INPUT -i eth0 -p tcp --syn -m state --state NEW --destination-port ! 22 -j NFQUEUE

to queue packets into nfq and had to check if the port the packet was directed to was open already.

Being able to match for packets which are directed to closed ports only, allows putting these packets into a netfilter_queue, and a userland application can retrieve the packets from the nfq, open the port and tell netfilter to let the packet continue its way.

iptables -t mangle -A PREROUTING -i eth0 -p tcp -m socket -j ACCEPT
iptables -t mangle -A PREROUTING -i eth0 -p tcp --syn -m state --state NEW -j NFQUEUE

Comments



2009/11/22/iptables_-_match_closed_ports.txt · Last modified: 2010/07/02 12:29 by common
chimeric.de = chi`s home Creative Commons License Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0