Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 14 Dec 2000 00:32:19 -0800
From:      "Crist J. Clark" <cjclark@reflexnet.net>
To:        freebsd-security@freebsd.org
Subject:   Extended ipfw Logging
Message-ID:  <20001214003219.K96105@149.211.6.64.reflexcom.com>

next in thread | raw e-mail | index | archive | help

--ZmUaFz6apKcXQszQ
Content-Type: text/plain; charset=us-ascii

I posted this to the freebsd-ipfw list, but thought some of those in
this group who do not follow that list might be interested too.


INTRODUCTION

I wanted to add some detail to the ipfw logging. Specificially, I
wanted TCP flags. However, once I started coding, I decided why not
toss just about every field of interest in. I have attached patches.


WHAT THE PATCHES DO

There are new fields for all packets. Data from the IP header, the IP
ID, TTL, and extra fragmentation information is printed for all types
of datagrams. TCP packets include additional information on sequence
number, acknowledgement number, and flags.

Here are examples. First, a TCP handshake, brief data exchange, and
close (a telnet to the echo port),

  ipfw: 400 Accept TCP 192.168.64.254:2932 192.168.64.20:7 f=0x02 s=0x7feef91d a=0x00000000 i=0x48a9 t=0x40 in via ep0 DF
  ipfw: 400 Accept TCP 192.168.64.20:7 192.168.64.254:2932 f=0x12 s=0xeaa736a6 a=0x7feef91e i=0x0080 t=0x40 out via ep0 DF
  ipfw: 400 Accept TCP 192.168.64.254:2932 192.168.64.20:7 f=0x10 s=0x7feef91e a=0xeaa736a7 i=0x48aa t=0x40 in via ep0 DF
  ipfw: 400 Accept TCP 192.168.64.254:2932 192.168.64.20:7 f=0x18 s=0x7feef91e a=0xeaa736a7 i=0x48ca t=0x40 in via ep0 DF
  ipfw: 400 Accept TCP 192.168.64.20:7 192.168.64.254:2932 f=0x18 s=0xeaa736a7 a=0x7feef925 i=0x0083 t=0x40 out via ep0 DF
  ipfw: 400 Accept TCP 192.168.64.254:2932 192.168.64.20:7 f=0x10 s=0x7feef925 a=0xeaa736ae i=0x48cb t=0x40 in via ep0 DF
  ipfw: 400 Accept TCP 192.168.64.254:2932 192.168.64.20:7 f=0x11 s=0x7feef925 a=0xeaa736ae i=0x48ee t=0x40 in via ep0 DF
  ipfw: 400 Accept TCP 192.168.64.20:7 192.168.64.254:2932 f=0x10 s=0xeaa736ae a=0x7feef926 i=0x0086 t=0x40 out via ep0 DF
  ipfw: 400 Accept TCP 192.168.64.20:7 192.168.64.254:2932 f=0x11 s=0xeaa736ae a=0x7feef926 i=0x0087 t=0x40 out via ep0 DF
  ipfw: 400 Accept TCP 192.168.64.254:2932 192.168.64.20:7 f=0x10 s=0x7feef926 a=0xeaa736af i=0x48f0 t=0x40 in via ep0 DF

Here is UDP (a timed update),

  ipfw: 400 Accept UDP 192.168.64.254:525 192.168.64.20:525 i=0x4bb8 t=0x40 in via ep0
  ipfw: 400 Accept UDP 192.168.64.20:525 192.168.64.254:525 i=0x008b t=0x40 out via ep0
  ipfw: 400 Accept UDP 192.168.64.254:525 192.168.64.255:525 i=0x4bb9 t=0x40 in via ep

And finally, some fragmentation and ICMP (an oversized ping),

  ipfw: 400 Accept ICMP:8.0 192.168.64.254 192.168.64.20 i=0x5038 t=0xff in via ep0 Frag=0+
  ipfw: 400 Accept ICMP 192.168.64.254 192.168.64.20 i=0x5038 t=0xff in via ep0 Frag=1480+
  ipfw: 400 Accept ICMP 192.168.64.254 192.168.64.20 i=0x5038 t=0xff in via ep0 Frag=2960
  ipfw: 400 Accept ICMP:0.0 192.168.64.20 192.168.64.254 i=0x0095 t=0xff out via ep0

There are more fields that could be done, but this is all I was
interested in doing when coding.


HOW TO INSTALL AND CONTROL

Simply use patch(1) to apply the attached patches to your kernel
source. The patches were made and tested on 5-CURRENT, but they will
apply cleanly to 4-STABLE and I don't see why they would function any
differently. To enable the patches in your kernel, add,

  options	IPFIREWALL_EXTRA_VERBOSE

To your kernel config.

The patches use the net.inet.ip.fw.verbose sysctl knob,

  net.inet.ip.fw.verbose=0		# No logging
  net.inet.ip.fw.verbose=1		# Standard logging
  net.inet.ip.fw.verbose=2		# Enhanced logging logging

So once compiled in, the changes can be switched on the fly. When the
kernel is compiled with IPFIREWALL_EXTRA_VERBOSE, the verbose level of
'2' is the default after reboot.


SECURITY AND PERFORMANCE ISSUES

I was questioned whether this might make a firewall box easier to
DoS. I do not think there is any significant threat above that of a
box with standard logging. If you have a look at the patches, there is
not a whole lot of new code (although we are making snprintf(3)
calls). If you already have logging running, I doubt the change in
performance would be noticable.

Another point someone brought up was whether this might overflow logs
because you will not be getting 'last message repeated' lines from
syslogd. Since the IP ID and other fields should be changing for every
packet, you will not be seeing those. This might start to fill up logs
more if you are having misconfiguration problems, but I do not think
it makes the box easier to attack. It is trivial for an attacker to
mix things up so that you will not get 'last message repeated'
lines. Take something like a Smurf for example. You would be getting
pounded from multiple source addresses.

To summarize, if you want more information in your logs, these patches
should give you more of what you want with little to no cost. If
anyone has suggestions, bugs, criticism, or praise, send it
along. Obviously, if it is something that you think others on the list
might wish to discuss, CC the list. Otherwise, feel free to send mail
directly to me.


LOGGING AND CAPTURE DAEMON

Another thing I was considering was the idea of making a more
configurable logging utility and possibly a utility that will even
capture packets. The magic of divert(4) sockets make it fairly
straightforward to do these things in userland where you can add new
abilities without worrying about bloating or breaking the kernel. This
is similar to how some other firewall tools work.

In addition to more configurable and expandable logging, I was
considering the capability to capture raw packets. Now, I really do
not think trying to build something like a fully loaded IDS from this
is worthwhile when you have great tools like Snort available, but
I think its usefulness for debugging a firewall would be reason
enough and any actual security uses people find would be great.

I have not really decided if I am going to do this. If I no one else
is interested, I think I am best off just customizing my FreeBSD
kernel code as needed or making a really basic (not necessarily user
friendly or well documented) userland logger.

Thanks. Have fun with the patches and please let me know if you are
using them.
-- 
Crist J. Clark                           cjclark@alum.mit.edu

--ZmUaFz6apKcXQszQ
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="ip_fw.patch"

--- ip_fw.c	Sun Dec 10 19:13:17 2000
+++ /usr/src/sys/netinet/ip_fw.c	Wed Dec 13 23:52:04 2000
@@ -67,7 +67,11 @@
 
 static int fw_debug = 1;
 #ifdef IPFIREWALL_VERBOSE
+#ifdef IPFIREWALL_EXTRA_VERBOSE
+static int fw_verbose = 2;
+#else
 static int fw_verbose = 1;
+#endif
 #else
 static int fw_verbose = 0;
 #endif
@@ -488,7 +492,7 @@
     struct icmp *const icmp = (struct icmp *) ((u_int32_t *) ip + ip->ip_hl);
     u_int64_t count;
     char *action;
-    char action2[32], proto[47], name[18], fragment[17];
+    char action2[32], proto[97], name[18], fragment[17];
     int len;
 
     count = f ? f->fw_pcnt : ++counter;
@@ -572,9 +576,18 @@
 		    len += snprintf(SNPARGS(proto, len), " ");
 	    len += snprintf(SNPARGS(proto, len), "%s",
 		inet_ntoa(ip->ip_dst));
-	    if ((ip->ip_off & IP_OFFMASK) == 0)
-		    snprintf(SNPARGS(proto, len), ":%d",
+	    if ((ip->ip_off & IP_OFFMASK) == 0) {
+		    len += snprintf(SNPARGS(proto, len), ":%d",
 			ntohs(tcp->th_dport));
+#ifdef IPFIREWALL_EXTRA_VERBOSE
+		    if ( fw_verbose > 1 )
+			     len += snprintf(SNPARGS(proto, len),
+				 " f=0x%02x s=0x%08x a=0x%08x",
+				 tcp->th_flags,
+				 ntohl(tcp->th_seq),
+				 ntohl(tcp->th_ack));
+#endif
+	    }
 	    break;
     case IPPROTO_UDP:
 	    len = snprintf(SNPARGS(proto, 0), "UDP %s",
@@ -587,7 +600,7 @@
 	    len += snprintf(SNPARGS(proto, len), "%s",
 		inet_ntoa(ip->ip_dst));
 	    if ((ip->ip_off & IP_OFFMASK) == 0)
-		    snprintf(SNPARGS(proto, len), ":%d",
+		    len += snprintf(SNPARGS(proto, len), ":%d",
 			ntohs(udp->uh_dport));
 	    break;
     case IPPROTO_ICMP:
@@ -598,20 +611,46 @@
 		    len = snprintf(SNPARGS(proto, 0), "ICMP ");
 	    len += snprintf(SNPARGS(proto, len), "%s",
 		inet_ntoa(ip->ip_src));
-	    snprintf(SNPARGS(proto, len), " %s", inet_ntoa(ip->ip_dst));
+	    len += snprintf(SNPARGS(proto, len), " %s", inet_ntoa(ip->ip_dst));
 	    break;
     default:
 	    len = snprintf(SNPARGS(proto, 0), "P:%d %s", ip->ip_p,
 		inet_ntoa(ip->ip_src));
-	    snprintf(SNPARGS(proto, len), " %s", inet_ntoa(ip->ip_dst));
+	    len += snprintf(SNPARGS(proto, len), " %s", inet_ntoa(ip->ip_dst));
 	    break;
     }
 
-    if ((ip->ip_off & IP_OFFMASK))
+#ifdef IPFIREWALL_EXTRA_VERBOSE
+    if ( fw_verbose > 1 ) {
+	snprintf(SNPARGS(proto, len), 
+	    " i=0x%04x t=0x%02x",
+	    ntohs(ip->ip_id),
+	    ip->ip_ttl);
+	if (ip->ip_off & IP_DF)
+		len = snprintf(SNPARGS(fragment, 0), " DF");
+	else {
+		fragment[0] = '\0';
+		len = 0;
+	}
+	if (ip->ip_off & (IP_OFFMASK | IP_MF))
+		len += snprintf(SNPARGS(fragment, len), " Frag=%d",
+		    (ip->ip_off & IP_OFFMASK)<<3);
+	if (ip->ip_off & IP_MF)
+		len += snprintf(SNPARGS(fragment, len), "+");
+    } else {
+        if (ip->ip_off & (IP_OFFMASK | IP_MF))
+		snprintf(SNPARGS(fragment, 0), " Fragment = %d",
+	    	    ip->ip_off & IP_OFFMASK);
+        else
+		fragment[0] = '\0';
+    }
+#else
+    if (ip->ip_off & (IP_OFFMASK | IP_MF))
 	    snprintf(SNPARGS(fragment, 0), " Fragment = %d",
 		ip->ip_off & IP_OFFMASK);
     else
 	    fragment[0] = '\0';
+#endif
     if (oif)
 	    log(LOG_SECURITY | LOG_INFO, "%s %s %s out via %s%d%s\n",
 		name, action, proto, oif->if_name, oif->if_unit, fragment);

--ZmUaFz6apKcXQszQ
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="options.patch"

--- options	Sun Dec 10 18:25:56 2000
+++ /usr/src/sys/conf/options	Sun Dec 10 01:45:19 2000
@@ -245,6 +245,7 @@
 PFIL_HOOKS		opt_pfil_hooks.h
 IPFIREWALL		opt_ipfw.h
 IPFIREWALL_VERBOSE	opt_ipfw.h
+IPFIREWALL_EXTRA_VERBOSE	opt_ipfw.h
 IPFIREWALL_VERBOSE_LIMIT	opt_ipfw.h
 IPFIREWALL_DEFAULT_TO_ACCEPT	opt_ipfw.h
 IPFIREWALL_FORWARD		opt_ipfw.h

--ZmUaFz6apKcXQszQ--


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-security" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20001214003219.K96105>