Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 8 Jan 1999 19:33:32 +0100 (MET)
From:      mm@i.cz
To:        FreeBSD-gnats-submit@FreeBSD.ORG
Subject:   bin/9394: logging enhancements for natd 
Message-ID:  <199901081833.TAA23534@woody.i.cz>

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

>Number:         9394
>Category:       bin
>Synopsis:       enhancement to natd logging
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Fri Jan  8 10:40:01 PST 1999
>Closed-Date:
>Last-Modified:
>Originator:     Martin Machacek
>Release:        FreeBSD 3.0-CURRENT i386
>Organization:
ICZ a.s.
>Environment:

FreeBSD 3.0-CURRENT as of 8.1.1999, FreeBSD 2.2.8-RELEASE
natd v 1.8 natd v 1.2.2.6

>Description:

Natd allows to deny (drop) incoming packets on the external interface if there
is no translation entry for them (i.e they do not belong to any outgoing
connection). However these packets are logged only if natd is run in verbose
mode and they are logged along with all permitted packets on stdout. I believe
that it is important to have trace of all denied packets in order to be able
to detect possible attacks or network configuration problems. I think that
running natd in verbose mode is not a viable solution since the volume of logged
data is unneccerarily high. I've implemented simple enhancement that allows to
log only denied incoming packets via syslog. The patch adds new option log_denied
(yes/no value) that enables or disables logging. Further the patch adds new
option log_facility (string value) that allows to specify syslog facility to
be used for all logging through syslog. Default facility is LOG_DAEMON. Denied
packets are being logged with level LOG_WARNING. The patch adds new function
to natd.c (SyslogPacket) that formats data from the ip structure of the packet
to be dropped and logs them using the syslog function. The patch also modifies
the PrintPacket function in order to be consistent with the new SyslogPacket
function. The modification adds logging of UDP source and destination ports,
ICMP types and subtypes and IP types other that TCP,UDP and ICMP.
I've also created corresponding patch to the manpage describing both new options.
I'm running patched natd on quite heavily loaded firewall running FreeBSD 2.2.8
for 2 days without any problems. The patch helped me already to discover several
configuration problems in external part of my network and also helped me to 
detect one (admittedly harmless) portscan attack against the firewall. WARNING:
I haven't tried to neither to compile (due to currently broken build environment
on my CURRENT machine) nor to run the patched natd on FreeBSD 3.0 i(due to lack
of spare time) but both patches apply cleanly.

>How-To-Repeat:

Run unpatched natd with deny_incoming enabled and try to e.g. potscan the 
firewall machine from outside. No dropped packet will be logged anywhre unless
natd is run in verbose mode.

>Fix:
	
Apply patches (see bellow) to natd.c and natd.8 (both patches should work both
for the 3.0 and 2.2 branch).

########## natd.c.patch ################

*** natd.c.orig	Thu Jan  7 13:19:26 1999
--- natd.c	Thu Jan  7 18:57:57 1999
***************
*** 21,26 ****
--- 21,28 ----
  #include <netinet/ip.h>
  #include <machine/in_cksum.h>
  #include <netinet/tcp.h>
+ #include <netinet/udp.h>
+ #include <netinet/ip_icmp.h>
  #include <sys/ioctl.h>
  #include <net/if.h>
  #include <net/route.h>
***************
*** 35,41 ****
--- 37,45 ----
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
+ #define SYSLOG_NAMES
  #include <syslog.h>
+ #undef SYSLOG_NAMES
  #include <unistd.h>
  
  #include "natd.h"
***************
*** 56,61 ****
--- 60,66 ----
  static void	HandleRoutingInfo (int fd);
  static void	Usage ();
  static void	PrintPacket (struct ip*);
+ static void	SyslogPacket (struct ip*, int priority, char *label);
  static void	SetAliasAddressFromIfName (char* ifName);
  static void	InitiateShutdown ();
  static void	Shutdown ();
***************
*** 95,100 ****
--- 100,107 ----
  static	struct sockaddr_in	packetAddr;
  static 	int			packetSock;
  static  int			dropIgnoredIncoming;
+ static  int			logDropped;
+ static	int			logFacility;
  
  int main (int argc, char** argv)
  {
***************
*** 127,138 ****
--- 134,154 ----
  	aliasAddr.s_addr	= INADDR_NONE;
  	aliasOverhead		= 12;
  	dynamicMode		= 0;
+ 	logDropped		= 0;
+ 	logFacility		= LOG_DAEMON;
  /*
   * Mark packet buffer empty.
   */
  	packetSock		= -1;
  
  	ParseArgs (argc, argv);
+ 
+ /*
+  * Open syslog channel
+  */
+ 
+ openlog("natd", LOG_CONS | LOG_PID, logFacility);
+ 
  /*
   * Check that valid aliasing address has been given.
   */
***************
*** 463,469 ****
  			break;
  
  		default:
! 			printf ("[?]    ");
  			break;
  		}
  /*
--- 479,485 ----
  			break;
  
  		default:
! 			printf ("[%d]    ", ip->ip_p);
  			break;
  		}
  /*
***************
*** 487,492 ****
--- 503,511 ----
  		    dropIgnoredIncoming) {
  
  			printf (" dropped.\n");
+ 			if ( logDropped ) {
+ 				SyslogPacket(ip, LOG_WARNING, "denied");
+ 			}
  			return;
  		}
  	}
***************
*** 594,613 ****
  static void PrintPacket (struct ip* ip)
  {
  	struct tcphdr*	tcphdr;
  
! 	if (ip->ip_p == IPPROTO_TCP)
! 		tcphdr = (struct tcphdr*) ((char*) ip + (ip->ip_hl << 2));
! 	else
! 		tcphdr = NULL;
! 
! 	printf ("%s", inet_ntoa (ip->ip_src));
! 	if (tcphdr)
! 		printf (":%d", ntohs (tcphdr->th_sport));
! 
! 	printf (" -> ");
! 	printf ("%s", inet_ntoa (ip->ip_dst));
! 	if (tcphdr)
! 		printf (":%d", ntohs (tcphdr->th_dport));
  }
  
  static void SetAliasAddressFromIfName (char* ifName)
--- 613,671 ----
  static void PrintPacket (struct ip* ip)
  {
  	struct tcphdr*	tcphdr;
+ 	struct udphdr*	udphdr;
+ 	struct icmp*	icmphdr;
+ 	char		src[20];
+ 	char		dst[20];
+ 
+ 	strncpy(src, inet_ntoa (ip->ip_src), sizeof(src) - 1);
+ 	strncpy(dst, inet_ntoa (ip->ip_dst), sizeof(dst) - 1);
+ 	switch (ip->ip_p) {
+ 		case IPPROTO_TCP:
+ 			tcphdr = (struct tcphdr*) ((char*) ip + (ip->ip_hl << 2));
+ 			printf("%s:%d -> %s:%d", src, ntohs (tcphdr->th_sport), dst, ntohs (tcphdr->th_dport));
+ 		break;
+ 		case IPPROTO_UDP:
+ 			udphdr = (struct udphdr*) ((char*) ip + (ip->ip_hl << 2));
+ 			printf("%s:%d -> %s:%d", src, ntohs (udphdr->uh_sport), dst, ntohs (udphdr->uh_dport));
+ 		break;
+ 		case IPPROTO_ICMP:
+ 			icmphdr = (struct icmp*) ((char*) ip + (ip->ip_hl << 2));
+ 			printf("%s -> %s %d(%d)", src, dst, ntohs (icmphdr->icmp_type), ntohs (icmphdr->icmp_code));
+ 		break;
+ 		default:
+ 			printf("%s -> %s ", src, dst);
+ 		break;
+ 	}
+ }
  
! static void SyslogPacket (struct ip* ip, int priority, char *label)
! {
! 	struct tcphdr*	tcphdr;
! 	struct udphdr*	udphdr;
! 	struct icmp*	icmphdr;
! 	char		src[20];
! 	char		dst[20];
! 
! 	strncpy(src, inet_ntoa (ip->ip_src), sizeof(src) - 1);
! 	strncpy(dst, inet_ntoa (ip->ip_dst), sizeof(dst) - 1);
! 	switch (ip->ip_p) {
! 		case IPPROTO_TCP:
! 			tcphdr = (struct tcphdr*) ((char*) ip + (ip->ip_hl << 2));
! 			syslog(priority, "%s [TCP] %s:%d -> %s:%d", label, src, ntohs (tcphdr->th_sport), dst, ntohs (tcphdr->th_dport));
! 		break;
! 		case IPPROTO_UDP:
! 			udphdr = (struct udphdr*) ((char*) ip + (ip->ip_hl << 2));
! 			syslog(priority, "%s [UDP] %s:%d -> %s:%d", label, src, ntohs (udphdr->uh_sport), dst, ntohs (udphdr->uh_dport));
! 		break;
! 		case IPPROTO_ICMP:
! 			icmphdr = (struct icmp*) ((char*) ip + (ip->ip_hl << 2));
! 			syslog(priority, "%s [ICMP] %s -> %s %d(%d)", label, src, dst, ntohs (icmphdr->icmp_type), ntohs (icmphdr->icmp_code));
! 		break;
! 		default:
! 			syslog(priority,"%s [%d] %s -> %s ", label, ip->ip_p, src, dst);
! 		break;
! 	}
  }
  
  static void SetAliasAddressFromIfName (char* ifName)
***************
*** 761,767 ****
  	RedirectPort,
  	RedirectAddress,
  	ConfigFile,
! 	DynamicMode
  };
  
  enum Param {
--- 819,827 ----
  	RedirectPort,
  	RedirectAddress,
  	ConfigFile,
! 	DynamicMode,
! 	LogDenied,
! 	LogFacility
  };
  
  enum Param {
***************
*** 922,928 ****
  		"file_name",
  		"read options from configuration file",
  		"config",
! 		"f" }
  };
  	
  static void ParseOption (char* option, char* parms, int cmdLine)
--- 982,1005 ----
  		"file_name",
  		"read options from configuration file",
  		"config",
! 		"f" },
! 
! 	{ LogDenied,
! 		0,
! 		YesNo,
! 	        "[yes|no]",
! 		"enable logging of denied incoming packets",
! 		"log_denied",
! 		NULL },
! 
! 	{ LogFacility,
! 		0,
! 		String,
! 	        "facility",
! 		"name of syslog facility to use for logging",
! 		"log_facility",
! 		NULL }
! 
  };
  	
  static void ParseOption (char* option, char* parms, int cmdLine)
***************
*** 937,942 ****
--- 1014,1020 ----
  	struct in_addr		addrValue;
  	int			max;
  	char*			end;
+ 	CODE* 			fac_record = NULL;
  /*
   * Find option from table.
   */
***************
*** 1069,1074 ****
--- 1147,1172 ----
  
  	case ConfigFile:
  		ReadConfigFile (strValue);
+ 		break;
+ 
+ 	case LogDenied:
+ 		logDropped = 1;
+ 		break;
+ 
+ 	case LogFacility:
+ 
+ 		fac_record = facilitynames;
+ 		while (fac_record->c_name != NULL) {
+ 			if(!strcmp(fac_record->c_name, strValue)) {
+ 				logFacility = fac_record->c_val;
+ 				break;
+ 			} else {
+ 				fac_record++;
+ 			}
+ 		}
+ 		if(fac_record->c_name == NULL) {
+ 			errx(1, "Unknown log facility name: %s", strValue);	
+ 		}
  		break;
  	}
  }


###### natd.8.patch ####################

*** natd.8.orig	Fri Jan  8 18:30:25 1999
--- natd.8	Fri Jan  8 18:42:53 1999
***************
*** 22,30 ****
--- 22,32 ----
  .Nm
  .Op Fl log
  .Op Fl deny_incoming
+ .Op Fl log_denied
  .Op Fl use_sockets
  .Op Fl same_ports
  .Op Fl verbose
+ .Op Fl log_facility Ar facility_name
  .Op Fl unregistered_only
  .Op Fl permanent_link
  .Op Fl dynamic
***************
*** 74,79 ****
--- 76,89 ----
  .It Fl deny_incoming | d
  Reject packets destined for the current IP number that have no entry
  in the internal translation table.
+ 
+ .It Fl log_denied
+ Log denied incoming packets via syslog (see also log_facility)
+ 
+ .It Fl log_facility Ar facility_name
+ Use specified log facility when logging information via syslog.
+ Facility names are as in
+ .Xr syslog.conf 5
  
  .It Fl use_sockets | s
  Allocate a

>Release-Note:
>Audit-Trail:
>Unformatted:

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



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