ipfwd

ipfwd is a ip protocol redirection utility.  It is intended to help
forward non-tcp packets across a firewall.

ipfwd can optionally masquerade the forwarded packets, so that packets
still appear to have come from their original source, even after
retransmission by ipfwd from the localhost.

---------------------------------------------------------------------
An example will (hopefully) clarify usage:

 ipfwd was originally written to support passage of Microsoft's PPTP
(point to point tunneling protocol) across a firewall running linux
2.0.30.  PPTP consists of two portions: a 'control connection' from
source to destination on TCP port 1723, and bidirectional gre-encapsulated
tunnel data, which is transmitted using unadorned IP protocol 47.  The
standard linux firewall tools handle the TCP gateway without problems,
but are not able to filter based on IP protocol.   IP protocol 47 was
getting out (the firewall was configured to allow anything *out*), but
I wanted to dial *in*!

The solution is ipfwd (of course!).  A clean gateway requires
firewall tools and some clever masquerading.

We want to establish two seperate gateways: one for TCP port 1723, and
one for IP protocol 47.

For illustrative purposes, we will initially create the TCP gateway
using the redir tool, available from
  ftp://ftp.redhat.com/pub/contrib/i386/redir-0.7-1.i386.rpm
  http://sunsite.unc.edu/pub/Linux/system/network/daemons/redir-0.7.tar.gz

[Of course, you'll have to check the site for the latest version]

For the purpose of example, 172.24.24.24 is our internal PPTP
end-point, 172.24.0.1 is our firewall/gateway (the machine we're
running ipfwd on), and 199.183.24.226 is the outside host we want to
dial in from (the external PPTP end-point).

We set up the TCP gateway:
    redir 172.24.24.24 1723 1723 &

Fine.  We set up the inward-bound IP gateway:
    ipfwd 172.24.24.24 47

And now we're stuck.  We want to allow IP protocol 47 to get *out* the
firewall, as well, but we have a problem.  External host
199.183.24.226 opens a connection an externally visible interface on
the firewall.  redir forwards these packets on to the internal PPTP
end-point, 172.24.24.24.  From 172.24.24.24's viewpoint, this
connection is coming from 172.24.0.1, the firewall machine running
redir.  So it sends its replies back to 172.24.0.1.  With
bidirectional TCP, this is fine:  the socket on port 1723 is still
open, so redir shoves these packets back on the (still open)
connection to the external host.  Wonderful.  Now the external PPTP
end-point sends an IP protocol 47 message.  It reaches 172.24.0.1, our
firewall, and ipfwd tosses it over to 172.24.24.24, the PPTP
end-point.  BUT IP protocol packets are *not* connection oriented.  So
when our internal PPTP end-point reverses the connection we wind up
with IP packets at 172.24.0.1 AND WE HAVE NO IDEA WHERE TO SEND THEM!
We can hack around this if there is only a single external IP packet
source, but if we have multiple hosts sending IP packets at us we get
lost very quickly.  How do we sort out all the return packets?

The solution is some clever IP spoofing.  We install a masquerading
gateway.  For the TCP side, we'll need a package called 'ipportfw'.
Quoting the documentation:

  [See http://www.monmouth.demon.co.uk/ipsubs/portforwarding.html ]

   Download the kernel patches from the main site:
   ftp://ftp.ox.compsoc.org.uk/pub/users/steve/ipsubs/subs-patch-1.31.gz
   or the backup site (normally much faster to the US):
   http://www.monmouth.demon.co.uk/ipsubs/subs-patch-1.31.gz
   
   Also download the configuration tool (I could have adapted ipfwadm but
   there already enough versions of this tool so it would have further
   confused the problem) from:
   ftp://ftp.ox.compsoc.org.uk/pub/users/steve/ipsubs/ipportfw.c
   or the backup site (normally much faster to the US):
   http://www.monmouth.demon.co.uk/ipsubs/ipportfw.c

This will allow you to masquerade an *incoming* connection; the
standard linux masquerade only allows adjusting *outgoing* packets.

From my configuration files:

   # forward (TCP portion of) PPTP connections to internal PPTP end-point
   /sbin/ipportfw -A -t ext.ip.addr.here/1723 -R 172.24.24.24/1723

This does roughly the same thing as the previous 'redir' command *BUT*
the packets on the internal network are 'masqueraded' so that they
still appear to be coming from the original host.  So I connect from
199.183.24.226 to my gateway machine (on interface ext.ip.addr.here),
and ipportfw ensures that packets appear on my internal net destined
for 172.24.24.24, BUT STILL APPEARING TO COME FROM 199.183.24.226,
even though my firewall retransmitted them.  Now my internal machine
knows which external machine to send to.  Because I have done

  /sbin/ipfwadm -F -a accept -m -S 172.24.0.0/16 -D 0.0.0.0/0

my TCP and IP transmissions FROM my PPTP endpoint (172.24.24.24) get
back out to 199.183.24.226 just fine.  Note that we use the internal
linux masquerading on the return path, so that 199.183.24.226 is
convinced that it is talking to the firewall.  It sends an IP-47 packet
back to the firewall.  We have

   # forward (IP protocol 47 of) PPTP connections to 172.24.24.24
   /sbin/ipfwd --masq 172.24.24.24 47 &

in our configuration, so the IP protocol 47 packet is picked up and
sent off to 172.24.24.24.  Since we added the --masq option to ipfwd,
the packets appear to be coming from the outside, 199.183.24.226.
The internal PPTP end-point sends its replies back to the outside
address, linux again handles the masquerading, and we're set.
Everything works.
---------------------------------------------------------------

If you're really interested in PPTP gateways, you may wish to look at the
  ms-pptp-support
patch, which allows *outgoing* masquerading of PPTP connections. Look at
  http://www.wolfenet.com/~jhardin/
for more information.

Note that, due to the wonders of ip masquerading, the above set-up
works bidirectionally without flaw, *AND* supports an unlimited number
of both incoming and outgoing PPTP connections.   HOWEVER, linux
doesn't support filtering based on IP protocol, so if you don't want
to leave your outgoing gateway open to all traffic, as I did, you need
a tool to open *just* IP proto 47 and TCP port 1723 so that packets
*out* your gateway.  The above patch will do that.

I've written ipfwd as generally as possible; hopefully will be useful
to solve other IP-protocol firewall problems.  If you've got a
non-PPTP application of ipfwd, let me know so I can mention it here.

For more information, see the Linux-Firewall and Linux-Masquerading
HOWTOs.  They can be found at:

   http://sunsite.unc.edu/LDP/HOWTO/Firewall-HOWTO.html
and
   http://sunsite.unc.edu/LDP/HOWTO/mini/IP-Masquerade

More information on Microsoft PPTP can be found at
   http://www.microsoft.com/ntserver/communications/pptp.htm
and
   http://ds1.internic.net/internet-drafts/draft-ietf-pppext-pptp-02.txt

One of these days I'm going to write a PPTP interface for linux.
Encourage me to do it if you'd be interested in the result.
                   -- C. Scott Ananian <cananian@alumni.princeton.edu>
                       10/21/97
