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 <dnelson@redwoodsoft.com> added.
  - Logging enhancements from Martin Machacek <mm@i.cz> added.

Obtained from: Ari Suutari <ari@suutari.iki.fi>
This commit is contained in:
Brian Somers 1999-03-07 18:23:56 +00:00
parent 50a63ab997
commit 59a7c61374
12 changed files with 564 additions and 244 deletions

View File

@ -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 <tedm@portsoft.com>.
- PPTP redirect support by Dru Nelson <dnelson@redwoodsoft.com> added.
- Logging enhancements from Martin Machacek <mm@i.cz> added.

View File

@ -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 <bsd.prog.mk>

View File

@ -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 <suutari@iki.fi>
*
* $Id: icmp.c,v 1.3 1997/12/27 19:31:11 alex Exp $
* $Id:$
*/
#include <stdlib.h>

View File

@ -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)

View File

@ -9,9 +9,11 @@
*
* Ari Suutari <suutari@iki.fi>
*
* $Id: natd.c,v 1.8 1997/12/27 19:31:11 alex Exp $
* $Id:$
*/
#define SYSLOG_NAMES
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
@ -21,6 +23,8 @@
#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>
@ -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)

View File

@ -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 <suutari@iki.fi>
*
* $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);

View File

@ -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 <tedm@portsoft.com>.
- PPTP redirect support by Dru Nelson <dnelson@redwoodsoft.com> added.
- Logging enhancements from Martin Machacek <mm@i.cz> added.

View File

@ -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 <bsd.prog.mk>

View File

@ -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 <suutari@iki.fi>
*
* $Id: icmp.c,v 1.3 1997/12/27 19:31:11 alex Exp $
* $Id:$
*/
#include <stdlib.h>

View File

@ -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)

View File

@ -9,9 +9,11 @@
*
* Ari Suutari <suutari@iki.fi>
*
* $Id: natd.c,v 1.8 1997/12/27 19:31:11 alex Exp $
* $Id:$
*/
#define SYSLOG_NAMES
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
@ -21,6 +23,8 @@
#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>
@ -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)

View File

@ -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 <suutari@iki.fi>
*
* $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);