From 59a7c613740f5a3fa326a7941f2cffd700066376 Mon Sep 17 00:00:00 2001 From: Brian Somers Date: Sun, 7 Mar 1999 18:23:56 +0000 Subject: [PATCH] Upgrade (almost) to natd 2.0b1 - Transparent proxy support. - PERMANENT_LINK IS NOW OBSOLETE, use redirect_port instead. - Drop support for early FreeBSD 2.2 versions - If separate input & output sockets are being used use them to find out packet direction instead of normal mechanism. This can be handy in complex environments with multiple interfaces. - PPTP redirect support by Dru Nelson added. - Logging enhancements from Martin Machacek added. Obtained from: Ari Suutari --- sbin/natd/HISTORY | 22 ++++ sbin/natd/Makefile | 14 +-- sbin/natd/icmp.c | 6 +- sbin/natd/natd.8 | 76 +++++++----- sbin/natd/natd.c | 267 ++++++++++++++++++++++++++++------------- sbin/natd/natd.h | 19 +++ usr.sbin/natd/HISTORY | 22 ++++ usr.sbin/natd/Makefile | 14 +-- usr.sbin/natd/icmp.c | 6 +- usr.sbin/natd/natd.8 | 76 +++++++----- usr.sbin/natd/natd.c | 267 ++++++++++++++++++++++++++++------------- usr.sbin/natd/natd.h | 19 +++ 12 files changed, 564 insertions(+), 244 deletions(-) diff --git a/sbin/natd/HISTORY b/sbin/natd/HISTORY index cc59c4ece4eb..f929e80341a6 100644 --- a/sbin/natd/HISTORY +++ b/sbin/natd/HISTORY @@ -122,3 +122,25 @@ - Code cleanup work done in FreeBSD-current development merged. - Port numbers are now unsigned as they should always have been. + +* Version 1.12 + + - Typos in comment fixed. Copyright message added to + source & header files that were missing it. + - A small patch to libalias to make static NAT work correctly. + +* Version 2.0 + + - Upgrade to libalias 3.0 which gives: + - Transparent proxy support. + - permanent_link is now obsolete, use redirect_port instead. + - Drop support for early FreeBSD 2.2 versions + - If separate input & output sockets are being used + use them to find out packet direction instead of + normal mechanism. This can be handy in complex environments + with multiple interfaces. + - libalias is no longer part of this distribution. + - New sample configuration file + from Ted Mittelstaedt . + - PPTP redirect support by Dru Nelson added. + - Logging enhancements from Martin Machacek added. diff --git a/sbin/natd/Makefile b/sbin/natd/Makefile index 015d6458790d..b947158a8ebb 100644 --- a/sbin/natd/Makefile +++ b/sbin/natd/Makefile @@ -1,10 +1,8 @@ -# $Id:$ - -PROG= natd -SRCS= natd.c icmp.c -CFLAGS+=-Wall -LDADD= -lalias -DPADD= ${LIBALIAS} -MAN8= natd.8 +PROG = natd +SRCS = natd.c icmp.c +CFLAGS += -Wall +LDADD = -lalias +DPADD = ${LIBALIAS} +MAN8 = natd.8 .include diff --git a/sbin/natd/icmp.c b/sbin/natd/icmp.c index 9624efd10313..1a144c2f3a4b 100644 --- a/sbin/natd/icmp.c +++ b/sbin/natd/icmp.c @@ -1,13 +1,15 @@ /* + * natd - Network Address Translation Daemon for FreeBSD. + * * This software is provided free of charge, with no * warranty of any kind, either expressed or implied. * Use at your own risk. * - * You may copy, modify and distribute this software freely. + * You may copy, modify and distribute this software (icmp.c) freely. * * Ari Suutari * - * $Id: icmp.c,v 1.3 1997/12/27 19:31:11 alex Exp $ + * $Id:$ */ #include diff --git a/sbin/natd/natd.8 b/sbin/natd/natd.8 index 0e7110e29644..6202a94f9679 100644 --- a/sbin/natd/natd.8 +++ b/sbin/natd/natd.8 @@ -1,5 +1,5 @@ .\" manual page [] for natd 1.4 -.\" $Id: natd.8,v 1.14 1998/07/14 08:18:51 jkoshy Exp $ +.\" $Id:$ .Dd 15 April 1997 .Os FreeBSD .Dt NATD 8 @@ -10,7 +10,6 @@ Network Address Translation Daemon .Sh SYNOPSIS .Nm .Op Fl ldsmvu -.Op Fl permanent_link .Op Fl dynamic .Op Fl i Ar inport .Op Fl o Ar outport @@ -22,11 +21,12 @@ Network Address Translation Daemon .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 .Op Fl inport Ar inport .Op Fl outport Ar outport @@ -36,6 +36,10 @@ Network Address Translation Daemon .Op Fl config Ar configfile .Op Fl redirect_port Ar linkspec .Op Fl redirect_address Ar localIP publicIP +.Op Fl reverse +.Op Fl proxy_only +.Op Fl proxy_rule Ar proxyspec +.Op Fl pptpalias Ar localIP .Sh DESCRIPTION This program provides a Network Address Translation facility for use @@ -75,6 +79,14 @@ This file is truncated each time natd is started. 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 .Xr socket 2 @@ -102,13 +114,9 @@ Only alter outgoing packets with an unregistered source address. According to rfc 1918, unregistered source addresses are 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16. -.It Fl redirect_port Ar linkspec +.It Fl redirect_port Ar proto targetIP:targetPORT [aliasIP:]aliasPORT [remoteIP[:remotePORT]] Redirect incoming connections arriving to given port to another host and port. -Linkspec is of the form - - proto targetIP:targetPORT [aliasIP:]aliasPORT [remoteIP[:remotePORT]] - -where proto is either tcp or udp, targetIP is the desired target IP +Proto is either tcp or udp, targetIP is the desired target IP number, targetPORT is the desired target PORT number, aliasPORT is the requested PORT number and aliasIP is the aliasing address. RemoteIP and remotePORT can be used to specify the connection @@ -143,26 +151,6 @@ translated local address (192.168.0.4), but outgoing traffic to the first two addresses will still be aliased to specified public address. -.It Fl permanent_link Ar linkspec -Create a permanent entry in the internal alias table. Linkspec is -of the form - - proto targetIP:targetPORT sourceIP:sourcePORT aliasPORT - -where proto is either tcp or udp, targetIP is the desired target IP -number, targetPORT is the desired target PORT number, sourceIP and -sourcePORT match the incoming packet, and aliasPORT is the requested -PORT number. Values of zero are considered as wildcards. For example, -the argument - -.Ar tcp inside1:telnet outside1:0 6666 - -means that tcp packets destined for port 6666 on this machine from the -outside1 machine (any port) will be sent to the telnet port on the -inside1 machine. - -New installations are encouraged to use redirect_port instead. - .It Fl dynamic If the .Fl n @@ -272,6 +260,34 @@ is synonomous with .Fl log . Empty lines and lines beginning with '#' are ignored. +.It Fl reverse +Reverse operation of natd. This can be useful in some +transparent proxying situations when outgoing traffic +is redirected to the local machine and natd is running on the +incoming interface (it usually runs on the outgoing interface). + +.It Fl proxy_only +Force natd to perform transparent proxying +only. Normal address translation is not performed. + +.It Fl proxy_rule Ar [type encode_ip_hdr|encode_tcp_stream] port xxxx server a.b.c.d:yyyy +Enable transparent proxying. Packets with the given port going through this +host to any other host are redirected to the given server and port. +Optionally, the original target address can be encoded into the packet. Use +.Dq encode_ip_hdr +to put this information into the IP option field or +.Dq encode_tcp_stream +to inject the data into the beginning of the TCP stream. + +.It Fl pptpalias Ar localIP +Allow PPTP packets to go to the defined localIP address. PPTP is a VPN or secure +IP tunneling technology being developed primarily by Microsoft. For its encrypted traffic, +it uses an old IP encapsulation protocol called GRE (47). This +natd option will translate any traffic of this protocol to a +single, specified IP address. This would allow either one client or one server +to be serviced with natd. If you are setting up a server, don't forget to allow the TCP traffic +for the PPTP setup. For a client or server, you must allow GRE (protocol 47) if you have firewall lists active. + .El .Sh RUNNING NATD @@ -404,5 +420,7 @@ times: (IRC support & misc additions) .An Ari Suutari Aq suutari@iki.fi (natd) +.An Dru Nelson Aq dnelson@redwoodsoft.com +(PPTP support) .An Brian Somers Aq brian@awfulhak.org (glue) diff --git a/sbin/natd/natd.c b/sbin/natd/natd.c index 7b9ac6f899d9..585213562b19 100644 --- a/sbin/natd/natd.c +++ b/sbin/natd/natd.c @@ -9,9 +9,11 @@ * * Ari Suutari * - * $Id: natd.c,v 1.8 1997/12/27 19:31:11 alex Exp $ + * $Id:$ */ +#define SYSLOG_NAMES + #include #include #include @@ -21,6 +23,8 @@ #include #include #include +#include +#include #include #include #include @@ -51,20 +55,22 @@ * Function prototypes. */ -static void DoAliasing (int fd); +static void DoAliasing (int fd, int direction); static void DaemonMode (); static void HandleRoutingInfo (int fd); static void Usage (); +static char* FormatPacket (struct ip*); 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 (); static void RefreshAddr (); static void ParseOption (char* option, char* parms, int cmdLine); static void ReadConfigFile (char* fileName); -static void SetupPermanentLink (char* parms); static void SetupPortRedirect (char* parms); static void SetupAddressRedirect (char* parms); +static void SetupPptpAlias (char* parms); static void StrToAddr (char* str, struct in_addr* addr); static u_short StrToPort (char* str, char* proto); static int StrToProto (char* str); @@ -94,7 +100,10 @@ static char packetBuf[IP_MAXPACKET]; static int packetLen; static struct sockaddr_in packetAddr; static int packetSock; +static int packetDirection; static int dropIgnoredIncoming; +static int logDropped; +static int logFacility; int main (int argc, char** argv) { @@ -127,12 +136,19 @@ int main (int argc, char** argv) aliasAddr.s_addr = INADDR_NONE; aliasOverhead = 12; dynamicMode = 0; + logDropped = 0; + logFacility = LOG_DAEMON; /* * Mark packet buffer empty. */ packetSock = -1; + packetDirection = DONT_KNOW; ParseArgs (argc, argv); +/* + * Open syslog channel. + */ + openlog ("natd", LOG_CONS | LOG_PID, logFacility); /* * Check that valid aliasing address has been given. */ @@ -275,7 +291,7 @@ int main (int argc, char** argv) * When using only one socket, just call * DoAliasing repeatedly to process packets. */ - DoAliasing (divertInOut); + DoAliasing (divertInOut, DONT_KNOW); continue; } /* @@ -330,15 +346,15 @@ int main (int argc, char** argv) if (divertIn != -1) if (FD_ISSET (divertIn, &readMask)) - DoAliasing (divertIn); + DoAliasing (divertIn, INPUT); if (divertOut != -1) if (FD_ISSET (divertOut, &readMask)) - DoAliasing (divertOut); + DoAliasing (divertOut, OUTPUT); if (divertInOut != -1) if (FD_ISSET (divertInOut, &readMask)) - DoAliasing (divertInOut); + DoAliasing (divertInOut, DONT_KNOW); if (routeSock != -1) if (FD_ISSET (routeSock, &readMask)) @@ -402,7 +418,7 @@ static void ParseArgs (int argc, char** argv) } } -static void DoAliasing (int fd) +static void DoAliasing (int fd, int direction) { int bytes; int origBytes; @@ -437,17 +453,18 @@ static void DoAliasing (int fd) * This is a IP packet. */ ip = (struct ip*) packetBuf; + if (direction == DONT_KNOW) + if (packetAddr.sin_addr.s_addr == INADDR_ANY) + direction = OUTPUT; + else + direction = INPUT; if (verbose) { /* * Print packet direction and protocol type. */ - - if (packetAddr.sin_addr.s_addr == INADDR_ANY) - printf ("Out "); - else - printf ("In "); + printf (direction == OUTPUT ? "Out " : "In "); switch (ip->ip_p) { case IPPROTO_TCP: @@ -463,7 +480,7 @@ static void DoAliasing (int fd) break; default: - printf ("[?] "); + printf ("[%d] ", ip->ip_p); break; } /* @@ -472,13 +489,14 @@ static void DoAliasing (int fd) PrintPacket (ip); } - if (packetAddr.sin_addr.s_addr == INADDR_ANY) { + if (direction == OUTPUT) { /* * Outgoing packets. Do aliasing. */ PacketAliasOut (packetBuf, IP_MAXPACKET); } else { + /* * Do aliasing. */ @@ -486,7 +504,12 @@ static void DoAliasing (int fd) if (status == PKT_ALIAS_IGNORED && dropIgnoredIncoming) { - printf (" dropped.\n"); + if (verbose) + printf (" dropped.\n"); + + if (logDropped) + SyslogPacket (ip, LOG_WARNING, "denied"); + return; } } @@ -497,7 +520,7 @@ static void DoAliasing (int fd) /* * Update alias overhead size for outgoing packets. */ - if (packetAddr.sin_addr.s_addr == INADDR_ANY && + if (direction == OUTPUT && bytes - origBytes > aliasOverhead) aliasOverhead = bytes - origBytes; @@ -512,8 +535,10 @@ static void DoAliasing (int fd) printf ("\n"); } - packetLen = bytes; - packetSock = fd; + packetLen = bytes; + packetSock = fd; + packetDirection = direction; + FlushPacketBuffer (fd); } @@ -542,7 +567,7 @@ static void FlushPacketBuffer (int fd) if (errno == EMSGSIZE) { - if (packetAddr.sin_addr.s_addr == INADDR_ANY && + if (packetDirection == OUTPUT && ifMTU != -1) SendNeedFragIcmp (icmpSock, (struct ip*) packetBuf, @@ -593,21 +618,60 @@ static void HandleRoutingInfo (int fd) static void PrintPacket (struct ip* ip) { + printf ("%s", FormatPacket (ip)); +} + +static void SyslogPacket (struct ip* ip, int priority, char *label) +{ + syslog (priority, "%s %s", label, FormatPacket (ip)); +} + +static char* FormatPacket (struct ip* ip) +{ + static char buf[256]; struct tcphdr* tcphdr; + struct udphdr* udphdr; + struct icmp* icmphdr; + char src[20]; + char dst[20]; - if (ip->ip_p == IPPROTO_TCP) + strcpy (src, inet_ntoa (ip->ip_src)); + strcpy (dst, inet_ntoa (ip->ip_dst)); + + switch (ip->ip_p) { + case IPPROTO_TCP: tcphdr = (struct tcphdr*) ((char*) ip + (ip->ip_hl << 2)); - else - tcphdr = NULL; + sprintf (buf, "[TCP] %s:%d -> %s:%d", + src, + ntohs (tcphdr->th_sport), + dst, + ntohs (tcphdr->th_dport)); + break; - printf ("%s", inet_ntoa (ip->ip_src)); - if (tcphdr) - printf (":%d", ntohs (tcphdr->th_sport)); + case IPPROTO_UDP: + udphdr = (struct udphdr*) ((char*) ip + (ip->ip_hl << 2)); + sprintf (buf, "[UDP] %s:%d -> %s:%d", + src, + ntohs (udphdr->uh_sport), + dst, + ntohs (udphdr->uh_dport)); + break; - printf (" -> "); - printf ("%s", inet_ntoa (ip->ip_dst)); - if (tcphdr) - printf (":%d", ntohs (tcphdr->th_dport)); + case IPPROTO_ICMP: + icmphdr = (struct icmp*) ((char*) ip + (ip->ip_hl << 2)); + sprintf (buf, "[ICMP] %s -> %s %d(%d)", + src, + dst, + ntohs (icmphdr->icmp_type), + ntohs (icmphdr->icmp_code)); + break; + + default: + sprintf (buf, "[%d] %s -> %s ", ip->ip_p, src, dst); + break; + } + + return buf; } static void SetAliasAddressFromIfName (char* ifName) @@ -757,11 +821,14 @@ enum Option { Port, AliasAddress, InterfaceName, - PermanentLink, RedirectPort, RedirectAddress, ConfigFile, - DynamicMode + DynamicMode, + PptpAlias, + ProxyRule, + LogDenied, + LogFacility }; enum Param { @@ -811,6 +878,22 @@ static struct OptionInfo optionTable[] = { "log", "l" }, + { PacketAliasOption, + PKT_ALIAS_PROXY_ONLY, + YesNo, + "[yes|no]", + "proxy only", + "proxy_only", + NULL }, + + { PacketAliasOption, + PKT_ALIAS_REVERSE, + YesNo, + "[yes|no]", + "operate in reverse mode", + "reverse", + NULL }, + { PacketAliasOption, PKT_ALIAS_DENY_INCOMING, YesNo, @@ -891,12 +974,13 @@ static struct OptionInfo optionTable[] = { "interface", "n" }, - { PermanentLink, + { ProxyRule, 0, String, - "tcp|udp src:port dst:port alias", - "define permanent link for incoming connection", - "permanent_link", + "[type encode_ip_hdr|encode_tcp_stream] port xxxx server " + "a.b.c.d:yyyy", + "add transparent proxying / destination NAT", + "proxy_rule", NULL }, { RedirectPort, @@ -916,13 +1000,38 @@ static struct OptionInfo optionTable[] = { "redirect_address", NULL }, + { PptpAlias, + 0, + String, + "src", + "define inside machine for PPTP traffic", + "pptpalias", + NULL }, + { ConfigFile, 0, String, "file_name", "read options from configuration file", "config", - "f" } + "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,6 +1046,7 @@ static void ParseOption (char* option, char* parms, int cmdLine) struct in_addr addrValue; int max; char* end; + CODE* fac_record = NULL; /* * Find option from table. */ @@ -1047,10 +1157,6 @@ static void ParseOption (char* option, char* parms, int cmdLine) memcpy (&aliasAddr, &addrValue, sizeof (struct in_addr)); break; - case PermanentLink: - SetupPermanentLink (strValue); - break; - case RedirectPort: SetupPortRedirect (strValue); break; @@ -1059,6 +1165,14 @@ static void ParseOption (char* option, char* parms, int cmdLine) SetupAddressRedirect (strValue); break; + case PptpAlias: + SetupPptpAlias (strValue); + break; + + case ProxyRule: + PacketAliasProxyRule (strValue); + break; + case InterfaceName: if (ifName) free (ifName); @@ -1070,6 +1184,30 @@ static void ParseOption (char* option, char* parms, int cmdLine) 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; } } @@ -1154,60 +1292,23 @@ static void Usage () exit (1); } -void SetupPermanentLink (char* parms) +void SetupPptpAlias (char* parms) { char buf[128]; char* ptr; struct in_addr srcAddr; - struct in_addr dstAddr; - struct in_addr null_address; - u_short srcPort; - u_short dstPort; - u_short aliasPort; - int proto; - char* protoName; strcpy (buf, parms); -/* - * Extract protocol. - */ - protoName = strtok (buf, " \t"); - if (!protoName) - errx (1, "permanent_link: missing protocol"); - proto = StrToProto (protoName); /* * Extract source address. */ - ptr = strtok (NULL, " \t"); + ptr = strtok (buf, " \t"); if (!ptr) - errx (1, "permanent_link: missing src address"); + errx(1, "pptpalias: missing src address"); - srcPort = StrToAddrAndPort (ptr, &srcAddr, protoName); -/* - * Extract destination address. - */ - ptr = strtok (NULL, " \t"); - if (!ptr) - errx (1, "permanent_link: missing dst address"); - - dstPort = StrToAddrAndPort (ptr, &dstAddr, protoName); -/* - * Export alias port. - */ - ptr = strtok (NULL, " \t"); - if (!ptr) - errx (1, "permanent_link: missing alias port"); - - aliasPort = StrToPort (ptr, protoName); - - null_address.s_addr = 0; - PacketAliasRedirectPort (srcAddr, - srcPort, - dstAddr, - dstPort, - null_address, aliasPort, - proto); + StrToAddr (ptr, &srcAddr); + PacketAliasPptp (srcAddr); } void SetupPortRedirect (char* parms) diff --git a/sbin/natd/natd.h b/sbin/natd/natd.h index d3982415f34d..b45048ef4bb4 100644 --- a/sbin/natd/natd.h +++ b/sbin/natd/natd.h @@ -1,5 +1,24 @@ +/* + * natd - Network Address Translation Daemon for FreeBSD. + * + * This software is provided free of charge, with no + * warranty of any kind, either expressed or implied. + * Use at your own risk. + * + * You may copy, modify and distribute this software (natd.h) freely. + * + * Ari Suutari + * + * $Id:$ + */ + #define PIDFILE "/var/run/natd.pid" +#define INPUT 1 +#define OUTPUT 2 +#define DONT_KNOW 3 extern void Quit (char* msg); extern void Warn (char* msg); extern int SendNeedFragIcmp (int sock, struct ip* failedDgram, int mtu); + + diff --git a/usr.sbin/natd/HISTORY b/usr.sbin/natd/HISTORY index cc59c4ece4eb..f929e80341a6 100644 --- a/usr.sbin/natd/HISTORY +++ b/usr.sbin/natd/HISTORY @@ -122,3 +122,25 @@ - Code cleanup work done in FreeBSD-current development merged. - Port numbers are now unsigned as they should always have been. + +* Version 1.12 + + - Typos in comment fixed. Copyright message added to + source & header files that were missing it. + - A small patch to libalias to make static NAT work correctly. + +* Version 2.0 + + - Upgrade to libalias 3.0 which gives: + - Transparent proxy support. + - permanent_link is now obsolete, use redirect_port instead. + - Drop support for early FreeBSD 2.2 versions + - If separate input & output sockets are being used + use them to find out packet direction instead of + normal mechanism. This can be handy in complex environments + with multiple interfaces. + - libalias is no longer part of this distribution. + - New sample configuration file + from Ted Mittelstaedt . + - PPTP redirect support by Dru Nelson added. + - Logging enhancements from Martin Machacek added. diff --git a/usr.sbin/natd/Makefile b/usr.sbin/natd/Makefile index 015d6458790d..b947158a8ebb 100644 --- a/usr.sbin/natd/Makefile +++ b/usr.sbin/natd/Makefile @@ -1,10 +1,8 @@ -# $Id:$ - -PROG= natd -SRCS= natd.c icmp.c -CFLAGS+=-Wall -LDADD= -lalias -DPADD= ${LIBALIAS} -MAN8= natd.8 +PROG = natd +SRCS = natd.c icmp.c +CFLAGS += -Wall +LDADD = -lalias +DPADD = ${LIBALIAS} +MAN8 = natd.8 .include diff --git a/usr.sbin/natd/icmp.c b/usr.sbin/natd/icmp.c index 9624efd10313..1a144c2f3a4b 100644 --- a/usr.sbin/natd/icmp.c +++ b/usr.sbin/natd/icmp.c @@ -1,13 +1,15 @@ /* + * natd - Network Address Translation Daemon for FreeBSD. + * * This software is provided free of charge, with no * warranty of any kind, either expressed or implied. * Use at your own risk. * - * You may copy, modify and distribute this software freely. + * You may copy, modify and distribute this software (icmp.c) freely. * * Ari Suutari * - * $Id: icmp.c,v 1.3 1997/12/27 19:31:11 alex Exp $ + * $Id:$ */ #include diff --git a/usr.sbin/natd/natd.8 b/usr.sbin/natd/natd.8 index 0e7110e29644..6202a94f9679 100644 --- a/usr.sbin/natd/natd.8 +++ b/usr.sbin/natd/natd.8 @@ -1,5 +1,5 @@ .\" manual page [] for natd 1.4 -.\" $Id: natd.8,v 1.14 1998/07/14 08:18:51 jkoshy Exp $ +.\" $Id:$ .Dd 15 April 1997 .Os FreeBSD .Dt NATD 8 @@ -10,7 +10,6 @@ Network Address Translation Daemon .Sh SYNOPSIS .Nm .Op Fl ldsmvu -.Op Fl permanent_link .Op Fl dynamic .Op Fl i Ar inport .Op Fl o Ar outport @@ -22,11 +21,12 @@ Network Address Translation Daemon .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 .Op Fl inport Ar inport .Op Fl outport Ar outport @@ -36,6 +36,10 @@ Network Address Translation Daemon .Op Fl config Ar configfile .Op Fl redirect_port Ar linkspec .Op Fl redirect_address Ar localIP publicIP +.Op Fl reverse +.Op Fl proxy_only +.Op Fl proxy_rule Ar proxyspec +.Op Fl pptpalias Ar localIP .Sh DESCRIPTION This program provides a Network Address Translation facility for use @@ -75,6 +79,14 @@ This file is truncated each time natd is started. 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 .Xr socket 2 @@ -102,13 +114,9 @@ Only alter outgoing packets with an unregistered source address. According to rfc 1918, unregistered source addresses are 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16. -.It Fl redirect_port Ar linkspec +.It Fl redirect_port Ar proto targetIP:targetPORT [aliasIP:]aliasPORT [remoteIP[:remotePORT]] Redirect incoming connections arriving to given port to another host and port. -Linkspec is of the form - - proto targetIP:targetPORT [aliasIP:]aliasPORT [remoteIP[:remotePORT]] - -where proto is either tcp or udp, targetIP is the desired target IP +Proto is either tcp or udp, targetIP is the desired target IP number, targetPORT is the desired target PORT number, aliasPORT is the requested PORT number and aliasIP is the aliasing address. RemoteIP and remotePORT can be used to specify the connection @@ -143,26 +151,6 @@ translated local address (192.168.0.4), but outgoing traffic to the first two addresses will still be aliased to specified public address. -.It Fl permanent_link Ar linkspec -Create a permanent entry in the internal alias table. Linkspec is -of the form - - proto targetIP:targetPORT sourceIP:sourcePORT aliasPORT - -where proto is either tcp or udp, targetIP is the desired target IP -number, targetPORT is the desired target PORT number, sourceIP and -sourcePORT match the incoming packet, and aliasPORT is the requested -PORT number. Values of zero are considered as wildcards. For example, -the argument - -.Ar tcp inside1:telnet outside1:0 6666 - -means that tcp packets destined for port 6666 on this machine from the -outside1 machine (any port) will be sent to the telnet port on the -inside1 machine. - -New installations are encouraged to use redirect_port instead. - .It Fl dynamic If the .Fl n @@ -272,6 +260,34 @@ is synonomous with .Fl log . Empty lines and lines beginning with '#' are ignored. +.It Fl reverse +Reverse operation of natd. This can be useful in some +transparent proxying situations when outgoing traffic +is redirected to the local machine and natd is running on the +incoming interface (it usually runs on the outgoing interface). + +.It Fl proxy_only +Force natd to perform transparent proxying +only. Normal address translation is not performed. + +.It Fl proxy_rule Ar [type encode_ip_hdr|encode_tcp_stream] port xxxx server a.b.c.d:yyyy +Enable transparent proxying. Packets with the given port going through this +host to any other host are redirected to the given server and port. +Optionally, the original target address can be encoded into the packet. Use +.Dq encode_ip_hdr +to put this information into the IP option field or +.Dq encode_tcp_stream +to inject the data into the beginning of the TCP stream. + +.It Fl pptpalias Ar localIP +Allow PPTP packets to go to the defined localIP address. PPTP is a VPN or secure +IP tunneling technology being developed primarily by Microsoft. For its encrypted traffic, +it uses an old IP encapsulation protocol called GRE (47). This +natd option will translate any traffic of this protocol to a +single, specified IP address. This would allow either one client or one server +to be serviced with natd. If you are setting up a server, don't forget to allow the TCP traffic +for the PPTP setup. For a client or server, you must allow GRE (protocol 47) if you have firewall lists active. + .El .Sh RUNNING NATD @@ -404,5 +420,7 @@ times: (IRC support & misc additions) .An Ari Suutari Aq suutari@iki.fi (natd) +.An Dru Nelson Aq dnelson@redwoodsoft.com +(PPTP support) .An Brian Somers Aq brian@awfulhak.org (glue) diff --git a/usr.sbin/natd/natd.c b/usr.sbin/natd/natd.c index 7b9ac6f899d9..585213562b19 100644 --- a/usr.sbin/natd/natd.c +++ b/usr.sbin/natd/natd.c @@ -9,9 +9,11 @@ * * Ari Suutari * - * $Id: natd.c,v 1.8 1997/12/27 19:31:11 alex Exp $ + * $Id:$ */ +#define SYSLOG_NAMES + #include #include #include @@ -21,6 +23,8 @@ #include #include #include +#include +#include #include #include #include @@ -51,20 +55,22 @@ * Function prototypes. */ -static void DoAliasing (int fd); +static void DoAliasing (int fd, int direction); static void DaemonMode (); static void HandleRoutingInfo (int fd); static void Usage (); +static char* FormatPacket (struct ip*); 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 (); static void RefreshAddr (); static void ParseOption (char* option, char* parms, int cmdLine); static void ReadConfigFile (char* fileName); -static void SetupPermanentLink (char* parms); static void SetupPortRedirect (char* parms); static void SetupAddressRedirect (char* parms); +static void SetupPptpAlias (char* parms); static void StrToAddr (char* str, struct in_addr* addr); static u_short StrToPort (char* str, char* proto); static int StrToProto (char* str); @@ -94,7 +100,10 @@ static char packetBuf[IP_MAXPACKET]; static int packetLen; static struct sockaddr_in packetAddr; static int packetSock; +static int packetDirection; static int dropIgnoredIncoming; +static int logDropped; +static int logFacility; int main (int argc, char** argv) { @@ -127,12 +136,19 @@ int main (int argc, char** argv) aliasAddr.s_addr = INADDR_NONE; aliasOverhead = 12; dynamicMode = 0; + logDropped = 0; + logFacility = LOG_DAEMON; /* * Mark packet buffer empty. */ packetSock = -1; + packetDirection = DONT_KNOW; ParseArgs (argc, argv); +/* + * Open syslog channel. + */ + openlog ("natd", LOG_CONS | LOG_PID, logFacility); /* * Check that valid aliasing address has been given. */ @@ -275,7 +291,7 @@ int main (int argc, char** argv) * When using only one socket, just call * DoAliasing repeatedly to process packets. */ - DoAliasing (divertInOut); + DoAliasing (divertInOut, DONT_KNOW); continue; } /* @@ -330,15 +346,15 @@ int main (int argc, char** argv) if (divertIn != -1) if (FD_ISSET (divertIn, &readMask)) - DoAliasing (divertIn); + DoAliasing (divertIn, INPUT); if (divertOut != -1) if (FD_ISSET (divertOut, &readMask)) - DoAliasing (divertOut); + DoAliasing (divertOut, OUTPUT); if (divertInOut != -1) if (FD_ISSET (divertInOut, &readMask)) - DoAliasing (divertInOut); + DoAliasing (divertInOut, DONT_KNOW); if (routeSock != -1) if (FD_ISSET (routeSock, &readMask)) @@ -402,7 +418,7 @@ static void ParseArgs (int argc, char** argv) } } -static void DoAliasing (int fd) +static void DoAliasing (int fd, int direction) { int bytes; int origBytes; @@ -437,17 +453,18 @@ static void DoAliasing (int fd) * This is a IP packet. */ ip = (struct ip*) packetBuf; + if (direction == DONT_KNOW) + if (packetAddr.sin_addr.s_addr == INADDR_ANY) + direction = OUTPUT; + else + direction = INPUT; if (verbose) { /* * Print packet direction and protocol type. */ - - if (packetAddr.sin_addr.s_addr == INADDR_ANY) - printf ("Out "); - else - printf ("In "); + printf (direction == OUTPUT ? "Out " : "In "); switch (ip->ip_p) { case IPPROTO_TCP: @@ -463,7 +480,7 @@ static void DoAliasing (int fd) break; default: - printf ("[?] "); + printf ("[%d] ", ip->ip_p); break; } /* @@ -472,13 +489,14 @@ static void DoAliasing (int fd) PrintPacket (ip); } - if (packetAddr.sin_addr.s_addr == INADDR_ANY) { + if (direction == OUTPUT) { /* * Outgoing packets. Do aliasing. */ PacketAliasOut (packetBuf, IP_MAXPACKET); } else { + /* * Do aliasing. */ @@ -486,7 +504,12 @@ static void DoAliasing (int fd) if (status == PKT_ALIAS_IGNORED && dropIgnoredIncoming) { - printf (" dropped.\n"); + if (verbose) + printf (" dropped.\n"); + + if (logDropped) + SyslogPacket (ip, LOG_WARNING, "denied"); + return; } } @@ -497,7 +520,7 @@ static void DoAliasing (int fd) /* * Update alias overhead size for outgoing packets. */ - if (packetAddr.sin_addr.s_addr == INADDR_ANY && + if (direction == OUTPUT && bytes - origBytes > aliasOverhead) aliasOverhead = bytes - origBytes; @@ -512,8 +535,10 @@ static void DoAliasing (int fd) printf ("\n"); } - packetLen = bytes; - packetSock = fd; + packetLen = bytes; + packetSock = fd; + packetDirection = direction; + FlushPacketBuffer (fd); } @@ -542,7 +567,7 @@ static void FlushPacketBuffer (int fd) if (errno == EMSGSIZE) { - if (packetAddr.sin_addr.s_addr == INADDR_ANY && + if (packetDirection == OUTPUT && ifMTU != -1) SendNeedFragIcmp (icmpSock, (struct ip*) packetBuf, @@ -593,21 +618,60 @@ static void HandleRoutingInfo (int fd) static void PrintPacket (struct ip* ip) { + printf ("%s", FormatPacket (ip)); +} + +static void SyslogPacket (struct ip* ip, int priority, char *label) +{ + syslog (priority, "%s %s", label, FormatPacket (ip)); +} + +static char* FormatPacket (struct ip* ip) +{ + static char buf[256]; struct tcphdr* tcphdr; + struct udphdr* udphdr; + struct icmp* icmphdr; + char src[20]; + char dst[20]; - if (ip->ip_p == IPPROTO_TCP) + strcpy (src, inet_ntoa (ip->ip_src)); + strcpy (dst, inet_ntoa (ip->ip_dst)); + + switch (ip->ip_p) { + case IPPROTO_TCP: tcphdr = (struct tcphdr*) ((char*) ip + (ip->ip_hl << 2)); - else - tcphdr = NULL; + sprintf (buf, "[TCP] %s:%d -> %s:%d", + src, + ntohs (tcphdr->th_sport), + dst, + ntohs (tcphdr->th_dport)); + break; - printf ("%s", inet_ntoa (ip->ip_src)); - if (tcphdr) - printf (":%d", ntohs (tcphdr->th_sport)); + case IPPROTO_UDP: + udphdr = (struct udphdr*) ((char*) ip + (ip->ip_hl << 2)); + sprintf (buf, "[UDP] %s:%d -> %s:%d", + src, + ntohs (udphdr->uh_sport), + dst, + ntohs (udphdr->uh_dport)); + break; - printf (" -> "); - printf ("%s", inet_ntoa (ip->ip_dst)); - if (tcphdr) - printf (":%d", ntohs (tcphdr->th_dport)); + case IPPROTO_ICMP: + icmphdr = (struct icmp*) ((char*) ip + (ip->ip_hl << 2)); + sprintf (buf, "[ICMP] %s -> %s %d(%d)", + src, + dst, + ntohs (icmphdr->icmp_type), + ntohs (icmphdr->icmp_code)); + break; + + default: + sprintf (buf, "[%d] %s -> %s ", ip->ip_p, src, dst); + break; + } + + return buf; } static void SetAliasAddressFromIfName (char* ifName) @@ -757,11 +821,14 @@ enum Option { Port, AliasAddress, InterfaceName, - PermanentLink, RedirectPort, RedirectAddress, ConfigFile, - DynamicMode + DynamicMode, + PptpAlias, + ProxyRule, + LogDenied, + LogFacility }; enum Param { @@ -811,6 +878,22 @@ static struct OptionInfo optionTable[] = { "log", "l" }, + { PacketAliasOption, + PKT_ALIAS_PROXY_ONLY, + YesNo, + "[yes|no]", + "proxy only", + "proxy_only", + NULL }, + + { PacketAliasOption, + PKT_ALIAS_REVERSE, + YesNo, + "[yes|no]", + "operate in reverse mode", + "reverse", + NULL }, + { PacketAliasOption, PKT_ALIAS_DENY_INCOMING, YesNo, @@ -891,12 +974,13 @@ static struct OptionInfo optionTable[] = { "interface", "n" }, - { PermanentLink, + { ProxyRule, 0, String, - "tcp|udp src:port dst:port alias", - "define permanent link for incoming connection", - "permanent_link", + "[type encode_ip_hdr|encode_tcp_stream] port xxxx server " + "a.b.c.d:yyyy", + "add transparent proxying / destination NAT", + "proxy_rule", NULL }, { RedirectPort, @@ -916,13 +1000,38 @@ static struct OptionInfo optionTable[] = { "redirect_address", NULL }, + { PptpAlias, + 0, + String, + "src", + "define inside machine for PPTP traffic", + "pptpalias", + NULL }, + { ConfigFile, 0, String, "file_name", "read options from configuration file", "config", - "f" } + "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,6 +1046,7 @@ static void ParseOption (char* option, char* parms, int cmdLine) struct in_addr addrValue; int max; char* end; + CODE* fac_record = NULL; /* * Find option from table. */ @@ -1047,10 +1157,6 @@ static void ParseOption (char* option, char* parms, int cmdLine) memcpy (&aliasAddr, &addrValue, sizeof (struct in_addr)); break; - case PermanentLink: - SetupPermanentLink (strValue); - break; - case RedirectPort: SetupPortRedirect (strValue); break; @@ -1059,6 +1165,14 @@ static void ParseOption (char* option, char* parms, int cmdLine) SetupAddressRedirect (strValue); break; + case PptpAlias: + SetupPptpAlias (strValue); + break; + + case ProxyRule: + PacketAliasProxyRule (strValue); + break; + case InterfaceName: if (ifName) free (ifName); @@ -1070,6 +1184,30 @@ static void ParseOption (char* option, char* parms, int cmdLine) 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; } } @@ -1154,60 +1292,23 @@ static void Usage () exit (1); } -void SetupPermanentLink (char* parms) +void SetupPptpAlias (char* parms) { char buf[128]; char* ptr; struct in_addr srcAddr; - struct in_addr dstAddr; - struct in_addr null_address; - u_short srcPort; - u_short dstPort; - u_short aliasPort; - int proto; - char* protoName; strcpy (buf, parms); -/* - * Extract protocol. - */ - protoName = strtok (buf, " \t"); - if (!protoName) - errx (1, "permanent_link: missing protocol"); - proto = StrToProto (protoName); /* * Extract source address. */ - ptr = strtok (NULL, " \t"); + ptr = strtok (buf, " \t"); if (!ptr) - errx (1, "permanent_link: missing src address"); + errx(1, "pptpalias: missing src address"); - srcPort = StrToAddrAndPort (ptr, &srcAddr, protoName); -/* - * Extract destination address. - */ - ptr = strtok (NULL, " \t"); - if (!ptr) - errx (1, "permanent_link: missing dst address"); - - dstPort = StrToAddrAndPort (ptr, &dstAddr, protoName); -/* - * Export alias port. - */ - ptr = strtok (NULL, " \t"); - if (!ptr) - errx (1, "permanent_link: missing alias port"); - - aliasPort = StrToPort (ptr, protoName); - - null_address.s_addr = 0; - PacketAliasRedirectPort (srcAddr, - srcPort, - dstAddr, - dstPort, - null_address, aliasPort, - proto); + StrToAddr (ptr, &srcAddr); + PacketAliasPptp (srcAddr); } void SetupPortRedirect (char* parms) diff --git a/usr.sbin/natd/natd.h b/usr.sbin/natd/natd.h index d3982415f34d..b45048ef4bb4 100644 --- a/usr.sbin/natd/natd.h +++ b/usr.sbin/natd/natd.h @@ -1,5 +1,24 @@ +/* + * natd - Network Address Translation Daemon for FreeBSD. + * + * This software is provided free of charge, with no + * warranty of any kind, either expressed or implied. + * Use at your own risk. + * + * You may copy, modify and distribute this software (natd.h) freely. + * + * Ari Suutari + * + * $Id:$ + */ + #define PIDFILE "/var/run/natd.pid" +#define INPUT 1 +#define OUTPUT 2 +#define DONT_KNOW 3 extern void Quit (char* msg); extern void Warn (char* msg); extern int SendNeedFragIcmp (int sock, struct ip* failedDgram, int mtu); + +