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

    Tuesday Apr 10, 2007

    IPFilter 5.0.2

    Going further along with adding new things to IPFilter, some of the recent things I've worked on adding code for are:

    • selective flushing - to flush just things matching port 80:
      # ipnat -m 'tcp.port=80' -F
      # ipf -m 'tcp.port=80' -Fs

      A list can be given - "tcp.port=25,80". The full list of currently allowed words is:

      ip.addr, ip.p ip.src, ip.dst, tcp.port, tcp.dport,, udp.port, udp.dport,
    • the matching from flushing also applies to listing active entries:
      # ipnat -m 'port=80' -l
      # ipfstat -m 'port=80' -sl

      will respectively show only NAT or state matcing port 80.

    • the above syntax can be used in ipf rules like this
      pass in exp { 'tcp.port=25,80' } keep state

      (this is really experimental - how many fields are required for it to be attractive or is it just a waste of time?)

    • Active NAT/state entries can now be printed out in columns:
      # ipnat -O all -l | head -1
      # ipfstat -O all -sl | head -1

      will print out the names of columns. A list can be given:

      # ipnat -O oldsrcip,newsrcip,olddstip,newdstip -l

      And you can change the name at the top

      # ipfstat -O src=saddr,dst=addr -sl

      or just not print out the heading line at all:

      # ipnat -O all= -l

    Comments/thoughts/criticisms welcome.

    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 -;



    « July 2016