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>