Sunday Oct 07, 2007

UPnP daemon for Solaris/IPFilter

Over the last week or so, I've been working on porting a UPnP daemon called miniupnpd to IPFilter. Included in this effort was getting it to work on Solaris. You can download a copy of the source code now from This .tar.gz file contains a Makefile that is set for building with gcc on Solaris amd64. You will need to have the GNU make available to build it.

Getting it to work with IPFilter

The daemon will add ipnat rules (rdr's) and ipf rules to make sure your traffic gets in and through the system but you must have a head rule similar to this in your ipf.conf so that miniupnpd can add rules to let traffic in:

block in all head miniupnpd

You will also need two ipf rules to allow the multicast traffic in and the replies back out again:

pass in proto udp from any to port = 1900
pass out proto udp from any port = 1900 to any

Patches are in progress to make keep state work with multicast UDP.


Sunday Sep 23, 2007

IPFilter 4.1.26

It's been a while since I blogged about IPFilter. I've been attending to problems over the past few months in a fairly responsive manner. The one consistent message I get out of this is I need to do more testing. Sigh. Just developing code is much more fun :) Testing is for users ;) Of course if there are fewer features then there is also less to test and go wrong. A lot to be said for simplicity!


4.1.26 - Released 24 September 2007

  • Fix build problem for Solaris prior to S10U4

4.1.25 - Released 20 September 2007

  • stepping through structures with ioctls can lead to the wrong things being free'd and panics
  • if a NAT entry (such as an rdr) is created but the packet ends up being blocked, tear down the NAT entry.
  • fix fragment cache preventing keep state from functioning
  • fix handling of \\ to indicate a continued line in .conf files
  • include port ranges in the allowed input for ipf when using "port = ()"
  • only advance TCP state for packets on the leading edgeof the window.
  • using ipnat -l can lead to memory corruption in high stress situations
  • track TCP sequence numbers with NAT so that it can do timeout advances correctly inline with state
  • ICMP checksums for some redirect'd packets are not adjusted correctly.
  • IPv6 address components need to be explicitly cast to a 32bit pointer boundary so that compilers don't try to access them as two 64bit pieces (no guarantee is made that an Ipv6 address is on a 64bit aligned address)
  • filling up the ipauth packet queue can lead to no more packets being processed.
  • locking used to deref a nat entry causes a significant performance hit
  • m_pulldown isn't properly handled, leading to possible panics with ICMPv6 packets
  • IPv6 fragment handling doesn't allow for "keep frag" to work
  • build on Solaris10 Update4 with pfhooks in the kernel
  • logging of Ipv6 packets with extension headers fix - Miroslaw Luc

4.1.24 - Released 8 July 2007

  • patch from Stuart Remphrey to address recursive mutex lock with TCP state
  • add hash table bucket stats display to ipnat -s
  • give ASSERT some teeth for user compiles
  • initialising ipf_global, ipf_frcache, ipf_mutex should all be done very early on
  • do some caddr_t cleanup, where possible
  • fr_ref no longer tracks the number of children rules in a group for head rules
  • make sure all BCOPY\* have a value assigned to something
  • fix possible use of icmp pointer after pullup makes it invalid
  • resolve compile problems related to FreeBSD tree

4.1.23 - Released 31 May 2007

DNS Proxy

Today I imported a DNS proxy, that I've been hacking around on for a while, into CVS on sourceforge. As a proxy it currently does no caching of DNS queries and answers, it merely redirects them to another DNS server. What benefits does it bring then?

The primary reason for the proxy is access control of DNS queries. The proxy's main purpose is allow me to block DNS requests for, say, Or perhaps more appropriately, it allows me to block DNS requests for, etc - ie. advertising web sites and other sources of web page spam.

Because it has been written to work with IPFilter, it can correctly work with packets that are sent to the proxy through the use of rdr rules - i.e. it can function as a transparent proxy when in the path of DNS.

The source code is part of the IPFilter project on and can be seen at

Limitations? It currently only works with DNS over UDP and requires IPFilter to compile. Well, there are probably lots of other limitations too, at present, as the feature set is just starting to be fleshed out.

Related to this, I'm also working on putting a simpler proxy into IPFilter 5.0 itself that allows for filtering DNS packets based on the names in the queries.

The proxy can be downloaded from sourceforge at:

Sunday Jun 10, 2007

DNS proxy for IPFilter

There seem to be a few DNS proxies out there but all seemed aimed at doing proxy+cache without being seemingly easy to control what is accepted or denied. Plus none of them work with rdr rules in ipnat. And I got tired of bind being so big and hard to make work and I didn't want to dabble with the other main alternative (there would be more work trying to get it architected right to do the transparent stuff, I'm sure.)

So this was my weekend project. Oh, it does no caching (yet.) There are man pages in the .tgz.

Configuration goes something like this:

port fred 5053 transparent;
forwarders {,; };
acl all port fred { block \*.xxx;};
acl all port fred { allow; reject; };

To be used with rules like:

rdr fxp0 0/0 port 53 -> port 5053 udp

Also, seperate to this, there will be a dns proxy in IPfilter 5 that allows similar things to be done. That can be used on the outbound side of a firewall hosting named with map rules :)


IPFilter 4.1.23

In the never ending quest for perfection and chasing platform changes, this latest update fixes some bugs that are new and some that are old.

I've also added this extra line to "ipfstat -s" output:

        82% hash efficiency

The routing header problem is perhaps the most serious from a security perspective - if you weren't (or aren't) blocking these packets explicitly, e.g

block in quick with v6hdrs routing

then the presence of the routing header would cause ipf to not find the next (TCP/UDP) header in the correct place. A regression test (ipv6.5) has been added to check for dealing with IPv6 routing header packets.


4.1.23 - Released 31 May 2007

  • NAT was not always correctly fixing ICMP headers for errors
  • some TCP state steps when closing do not update timeouts, leading to them being removed prematurely.
  • fix compilation problems for netbsd 4.99
  • protect enumeration of lists in the kernel from callout interrupts on BSD without locking
  • fix various problems with IPv6 header checks: TCP/UDP checksum validation was not being done, fragmentation header parsed dangerously and routing header prevented others from being seen
  • fix gcc 4.2 compiler warnings
  • fix TCP/UDP checksum calculation for IPv6
  • fix reference after free'ing ipftoken memory

4.1.22 - Released 13 May 2007

  • fix endless loop when flushing state/NAT by idle time
  • 4.1.21 - Released 12 May 2007

    • show the number of states created against a rule with "-v" for ipfstat
    • fix build problems with FreeBSD
    • make it possible to flush the state table by idle time and TCP state
    • fix flushing out idle connections when state/NAT tables fill
    • print out the TCP state population with ipfstat/ipnat
    • stop creation of state table orphans via return-\*/fastroute
    • fix printing out of rule groups - they now only appear once

    4.1.20 - Released 30 April 2007

    • adjust TCP state numbers, making 11 closed (was 0) to better facilitate detecting closing connections that we can wipe out when a SYN arrives that matches the old
    • make it compile on Solaris10 Update3
    • structures used for ipf command ioctls weren't being freed in timeout fashion on solairs
    • use NL_EXPIRE, not ISL_EXPIRE, for expiring NAT sessions
    • adjust TCP timeout values and introduce a time-wait specifc timeout
    • to get a better TCP FSM emulation and one that can hopefully do a better job of cleaning up in a speedy fashion than previous
    • refactor the automatic flushing of TCP state entries when we fill up, but use the same algorithm as before but now it hopefully works
    • only 2 out of 4 interface names were being changed by ipfs when interface renaming was being used for state entries
    • add ipf_proxy_debug to ipf-T
    • matching of last fragments that had a number of bytes that wasn't a multiple of 8 failed
    • some combinations of TCP flags are considered bad aren't picked up as such, but these may be possible with T/TCP

    4.1.19 - Released 22 February 2007

    • Fix up compilation problems with NetBSD and Solaris.

    4.1.18 - Released 18 February 2007

    • fix compiling on Tru64
    • fix listing out filter rules with ipfstat (delete token at end of the list and detect zero rule being returned.)
    • fix extended flushing of NAT tables (was clearing out state tables)
    • fix null-pointer deref in hash table lookup
    • fix null-pointer deref in hash table lookup
    • fix NAT and stateful filtering with to/reply-to on destination interface

    4.1.17 - Released 20 January 2007

    • make flushing pools that are still in use mark them for deletion and have attempting to recreate them clear the delete flag
    • walking through the NAT tables with ioctls caused lock recursion
    • fix tracking TCP window scaling in the state code

    4.1.16 - Released 20 December 2006

    • allow rdr rules to only differ on the new port number
    • when creating state entry orphans, leave them on the linked list but not attached to the hash table and mark them visible as orphans in "ipfstat -sl"
    • log state removed when unloading differently to allow visible cues
    • return ipf ticks via SIOCGETGS for /dev/ipnat so "ipnat -l" can display ttl
    • abort logging a packet if the mbuf pointer is null when ipflog is called
    • Some NetBSD's have a selinfo.h instead of select.h
    • SIOCIPFFL was using copyoutptr and should have been using bcopy for /dev/ipauth
    • listing accounting rules using ioctl interface wasn't possible
    • fix leakage of state entries due to packets not matching up with NAT
    • improve ICMP error packet matching with state/NAT
    • fix problems with parsing and printing "-" as an interface name in ipnat.conf

    4.1.15 - Released 03 November 2006

    Wednesday Jan 17, 2007

    IPFilter 5.0.0 - feedback requested

    So i've been implementing some new features in ipfilter, whether or not they make it a 5.0, I'm not sure...maybe a few people can let me know what they think about that..

    So what are these new features?

    There are 3 new commands for ipnat.conf:

    • rewrite - change both source and address fields for incoming or outgoing packets
    • encap - encapsulated the packet in a new IP header (this will be compatible, I hope, with IPENCAP tunnels elsewhere0
    • divert - encapsulate the packet into an IP+UDP packet

    To help people use these, I've rewritten the ipnat.conf man page.


    A divert rule looks like this:

    divert in on le0 proto udp from any to any port = 53 -> src,54 dst,5300;

    note the ";" on the end of the line. To the left of the "->" is the original packet to be matched, on the right, the IP/UDP header to create and put in front of the packet. Reply packets from that socket will have the IP+UDP headers removed when they get back to IPFilter. I'm hoping this will provide cross-platform "divert" functionality but it needs more widespread testing than what I've been able to achieve.


    encap is pretty much the same as divert, minus the port numbers to the right of "->".


    Rewrites have a subset of the combined functionality of rdr/map rules. As an example of how the man page has been rewritten, I've included the contents of it for this new command below.


    You can now use ipmon.conf to as the place to specify how log records are sent to syslog (facility & priority) rather than needing to do it in filter rules.


    As part of the "keep state" options, you can now specify a rule group to which ICMP replies can be filtered by - "... keep state(icmp-head icmprules)"

    It is also now possible to position stateful filtering checks, inbound and outbound nat lookups. If this is done, the traditional checks are no longer performed. This is done as follows:

    call now fr_checkstate in on le0 from any to any
    call now fr_ipfnatin in on ppp0 all
    call now fr_ipfnatout out on bge0 from bge0/32 to any

    Oh, being 5.0.0, it is a development version, there's nothing release quality about it (well, you might argue that for others too .. >:->), this is just to get some feedback from people on features and enable some people to try/test a few things out beyond my limited scope. Perhaps most importantly, most of my work to date has been limited to using NetBSD.

    It can be downloaded from ip_fil5.0.0.tar.gz. MD5 (/home/darrenr/ip_fil5.0.0.tar.gz) = 7798797c1929cb55c182d3088f40b0b5

           Whilst the above two commands provide a lot of flexibility in changing
           addressing  fields  in packets, often it can be of benefit to translate
           both source and destination at the same time or to  change  the source
           address  on  input  or the destination address on output.  Doing all of
           these things can be accomplished using rewrite NAT rules.
           A rewrite rule requires the same level of packet  matching  as before,
           protocol  and  source/destination  information  but  in addition allows
           either in or out to be specified like this:
           rewrite in on ppp0 proto tcp from any to any port = 80 ->
                src 0/0 dst,3128;
           rewrite out on ppp0 from any to any ->
                src 0/32 dst;
           On the RHS we can specify both new source and  destination information
           to  place  into the packet being sent out.  As with other rules used in
           ipnat.conf, there are shortcuts syntaxes available to use the original
           address  information  (0/0) and the address associated with the network
           interface (0/32.)  For TCP and UDP, both address and  port information
           can  be  changed.   At  present it is only possible to specify either a
           range of port numbers to be used (X-Y) or a single port number (=X) as
           rewrite in on le0 proto tcp from any to any port = 80 ->
                src 0/0,2000-20000 dst,port = 3128;
           There  are four fields that are stepped through in enumerating  the num-
           ber space available for creating a new destination:
           source address
           source port
           destination address
           destination port
           If one of these happens to be a static then it will be skipped 
           and  the  next one incremented.  As an example:
           rewrite out on le0 proto tcp from any to any port = 80 ->
                src,5000-5999 dst,6000-6999;
           The translated packets would be:
           1st src=,5000 dst=,6000
           2nd src=,5000 dst=,6000
           3rd src=,5001 dst=,6000
           4th src=,5001 dst=,6000
           5th src=,5001 dst=,6001
           6th src=,5001 dst=,6001
           and so on.
           As  with  map  rules, it is possible to specify a range of addresses by
           including the word range before the addresses:
           rewrite from any to any port = 80 ->
                src - dst -;

    Monday Nov 06, 2006

    IPFilter 4.1.15 released

    The IPFilter steam train rolls on, with another version cut out primarily to deal with compilation issues on different platforms. As I'm writing this blog entry a few days after I uploaded it, I can already say that I'll need to stamp out a new release soon to deal with more of the same - issues with SuSE 10.1 are one problem, at 4.1.16 is around the corner somewhere, so is a 5.0 not far away, now that I've successfully brainstormed over the weekend just gone.

    There is one new significant change and that is the application of the state table automatic flushing algorithm to the NAT table. In the state table management, if it attempts to add more entries to the table than has been declared the maximum, it sets a flag for the flushing of the table to try a bit harder to free up some entries by cleaning out what could be considered dead wood.

    4.1.15 - Released 03 November 2006

    • Add in automatic flushing of NAT, like state, table if it fills up too much
    • Update comments in the code for NAT checksum adjustments
    • Fix compiling on FreeBSD 5.4 and 6.0
    • prevent panics from read/write IOs trying to use uninitialised structures
    • Newer NetBSD should use malloc() instead of MALLOC() in the kernel where the size is not staticly defined
    • Some gcc warning message cleanup from NetBSD
    • Missing include for on Solaris for poll work
    • NetBSD now uses opt_ipfilter.h, not opt_ipfilter_log.h

    Monday Oct 02, 2006

    IPFilter 4.1.14

    After what has possibly been too long, I've finally gotten around to rolling together version 4.1.14 of IPFilter.

    What took it so long?

    I got stuck into verifying all of the test results for NAT'd ICMP packets and their checksums, where unknowingly there was a bug in one of my test scripts I found by developing another path to verify checksums. Anyway, this is now done and I've a lot more confidence in the ability of IPFilter to correctly modify ICMP checksums now.

    There are two other significant changes with this version.

    The first is that output from "ipfstat -io" and similar is now all retrieved by using ioctls to iterate through in-memory lists. This should remedy that problem on Linux as well as other systems that use IPFilter and choose not to have a /dev/mem or /dev/kmem.

    The second is short pool names can now be used in filter rules like this:

    table role = ipf type = tree name = letters
            {; !;; };
    pass in from pool/letters to any

    Anyway, I think that's all for now. I'll be updating sourceforge later in the day/week.
    Cheers, Darren

    4.1.14 - Released 04 October 2006

    • rewrite checksum alteration for ICMP packets being NAT'd to use a sane algorithm that can be it needs better comments
    • fix 1 byte error in checksum validation perl script
    • remove unused files in lib directory
    • ipftest will say "bad-packet" if it has been freed rather than just "blocked"
    • make it possible to load IP address pools from external files in ippool.conf
    • update copyright messages in tools directory
    • consolidate ioctl hanlding source code into fil.c
    • make ipfstat, ippool, ipnat retrieve information via ioctls rather than /dev/kmem

    4.1.13 - Released 4 April 2006




    « July 2016