From owner-freebsd-bugs Fri Jan 8 10:40:12 1999 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id KAA05158 for freebsd-bugs-outgoing; Fri, 8 Jan 1999 10:40:12 -0800 (PST) (envelope-from owner-freebsd-bugs@FreeBSD.ORG) Received: from freefall.freebsd.org (freefall.FreeBSD.ORG [204.216.27.21]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id KAA05128 for ; Fri, 8 Jan 1999 10:40:07 -0800 (PST) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.8.8/8.8.5) id KAA20019; Fri, 8 Jan 1999 10:40:01 -0800 (PST) Received: from kamna.i.cz (kamna.i.cz [193.85.255.30]) by hub.freebsd.org (8.8.8/8.8.8) with SMTP id KAA03946 for ; Fri, 8 Jan 1999 10:34:05 -0800 (PST) (envelope-from martin@i.cz) Received: (qmail 9973 invoked from network); 8 Jan 1999 18:33:33 -0000 Received: from woody.i.cz (@193.85.255.60) by kamna.i.cz with SMTP; 8 Jan 1999 18:33:33 -0000 Received: (from root@localhost) by woody.i.cz (8.8.8/8.7.3) id TAA23534; Fri, 8 Jan 1999 19:33:32 +0100 (MET) Message-Id: <199901081833.TAA23534@woody.i.cz> Date: Fri, 8 Jan 1999 19:33:32 +0100 (MET) From: mm@i.cz Reply-To: mm@i.cz To: FreeBSD-gnats-submit@FreeBSD.ORG X-Send-Pr-Version: 3.2 Subject: bin/9394: logging enhancements for natd Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org >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 #include #include + #include + #include #include #include #include *************** *** 35,41 **** --- 37,45 ---- #include #include #include + #define SYSLOG_NAMES #include + #undef SYSLOG_NAMES #include #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