[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Masquerading IPSec connections on FreeBSD?



On Wed, Sep 04, 2002 at 11:10:58PM +0300, Patrick J. Okui wrote:
> Hi all,
> 
> I need to set up a firewall machine to masquerade IPSec clients on windows machines to remote IPsec servers.
> 
> There are patches to do this with the Linux kernels, but even when they patch cleanly, or you manually edit the
> sections that do not, there are still many errors during the compilation process.
> 
> Is there a way I can do this with FreeBSD? And if so, could someone point me to some docs? (A howto would 
> be nice :-) ).

Well, FreeBSD can do masquerading (NAT) and it also has reliable IPSEC
support in the kernel. I've used both in anger.

IMO the problems you are likely to come across are:

1. mixing masquerading and IPSEC on the same box; and
2. if you are interoperating with Windows IPSEC clients, getting key
exchange and client authentication to work.

To take this in a little more detail:

NAT
---
There are at least 3 NAT implementations you can choose from under FreeBSD:
(1) userland ppp (which links to libalias)
(2) ipfw plus natd
(3) ipfilter

I recommend the third: ipfilter has the advantage of running under a
variety of different Unixes, including Solaris, so learning it gives you a
skill you can apply elsewhere. The other advantage is that no userland NAT
daemon is required, which can be a big advantage when you have a complex NAT
scenario with multiple 'outside' interfaces, where with ipfw you would have
to run multiple natd instances and tortuous ipfw rulesets.

The documentation for ipfilter is here:
http://coombs.anu.edu.au/~avalon/
which is somewhat better than the rather ponderous man pages (man -a ipf).
You'll probably also find it instructive to look in /etc/rc.network to see
how it is initialised.

A simple NAT router can be set up something like this, assuming the
'outside' interface is fxp0 and the 'inside' network is 192.168.0.0/24:

[/etc/rc.conf]
gateway_enable="YES"
ipnat_enable="YES"

[/etc/ipnat.rules]
map fxp0 192.168.0.0/24 -> 0/32 proxy port ftp ftp/tcp
map fxp0 192.168.0.0/24 -> 0/32 portmap tcp/udp auto
map fxp0 192.168.0.0/24 -> 0/32

A more sophisticated setup would include some stateful firewall rules as
well:

[/etc/rc.conf]
ipfilter_enable="YES"
ipmon_enable="YES"
icmp_drop_redirect="YES"

[/etc/ipf.rules]
pass out quick on fxp0 from any to any keep state
pass in quick on fxp1   # trusted 'inside' interface
pass out quick on fxp1
pass in quick on lo0
pass out quick on lo0
block in log all
block out log all

When writing such rulesets bear in mind that each packet traversing the
firewall will hit these rules twice: e.g. from client to outside world, will
hit first as "in on fxp1" then again as "out on fxp0".

You can build a router like this without even recompiling the kernel, since
ipfilter load as a module, but if you are building a kernel you can
incorporate it using

options		IPFILTER
options		IPFILTER_LOG

IPSEC
-----
IPSEC support in the kernel is enabled by:

options		IPSEC
options		IPSEC_ESP

You can then set up statically-keyed IPSEC tunnels fairly easily. Assuming
the local net is 192.168.0.0/24 with outside IP 1.2.3.4, and the remote net
is 192.168.1.0/24 with outside IP 5.6.7.8, you can do something like this:

[/etc/rc.conf]
ipsec_enable="YES"

[/etc/ipsec.conf]
add 1.2.3.4 5.6.7.8 esp 12345
	-E des-cbc 0x1111111111111111
	-A hmac-md5 0x22222222222222222222222222222222;
add 5.6.7.8 1.2.3.4 esp 12345
	-E des-cbc 0x1111111111111111
	-A hmac-md5 0x22222222222222222222222222222222;
spdadd 192.168.0.0/24[any] 192.168.1.0/24[any] any
	-P out ipsec esp/tunnel/1.2.3.4-5.6.7.8/require;
spdadd 192.168.1.0/24[any] 192.168.0.0/24[any] any
	-P in ipsec esp/tunnel/5.6.7.8-1.2.3.4/require;

(actually you would normally choose a stronger cipher than DES, but the
above is based on a working config which I have, which had to interoperate
with another device which only supported "export" strength encryption)

There is some more in the FreeBSD handbook at
http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/ipsec.html

Unfortunately, such static keys are unlikely to be much use if you are
interoperating with roaming IPSEC clients. If you want to do dynamic key
exchange you can try playing with /usr/ports/security/racoon, but you may
well find it doesn't support dynamic policy yet (that is, the keys can be
dynamic, but the endpoints and subnets must be fixed). Authentication of key
exchange is a nightmare of its own.

The documentation for all this is, to be frank, dreadful. However it partly
suffers from IPSEC itself being so complicated. The FreeBSD IPSEC
implementation comes from Kame - http://www.kame.net/ - and you may want to
look at the documentation there. I notice there is a FreeBSD IPSEC
miniHOWTO.

If you are using firewall rules remember to open protocol 50 (ESP), and UDP
port 500 if you are doing key exchange. Having a firewall which logs blocked
packets is useful :-)

Problem 1: IPSEC and NAT don't mix
----------------------------------
If you want to do IPSEC and NAT on the same box, you are likely to come
across problems. These may include:

- the source IPs get NAT'd even though you didn't want them to be, because
your IPSEC traffic is routed via your 'outside' interface
- the kernel NATs the encapsulated packet rather than the raw unencrypted
packet (or vice versa, whichever you don't want to happen :-)
- you have complex policy requirements, e.g. "NAT the source address to A
when packets are routed down IPSEC tunnel X, but source address B when
packets are routed down IPSEC tunnel Y"

Some of this can be solved with careful ipnat.rules entries - e.g.

map fxp0 from 192.168.0.0/24 to ! 192.168.0.0/16 -> 0/32

which stops NAT taking place if the destination is also a 192.168 address
(typically, tunnelled traffic between your two 192.168 nets does _not_ want
to be NATed)

But anything more sophisticated and you may want to look at a userland IPSEC
implementation, where the IPSEC tunnel appears as a separate device ("tun0"
etc), which makes it much easier to control the NATing. FreeBSD has
/usr/ports/net/pipsecd but it's very old (1999) and probably very limited.

You may be better giving up and trying OpenBSD which has a longer history
of IPSEC support, and therefore one hopes is more mature. I'm afraid I don't
have any experience of this though.

Problem 2: key exchange and general IPSEC interoperability
----------------------------------------------------------
This is alluded to above. Even static-key IPSEC has many different
implementation options; once key exchange and roaming clients become
involved, you may find it's very difficult to get the darned things to talk
to each other.

If you have a budget for this, dare I say it but it may be worth buying
commercial software (e.g. Cequrux) or hardware (e.g. Netscreen) which has
fully supported Windows clients.

Do see if you can "try before you buy" though. In my experience even
commercial firewall boxes from different vendors which claim IPSEC
compliance can refuse to interoperate.

HTH,

Brian.

-----
This is the afnog mailing list, managed by Majordomo 1.94.5

To send a message to this list, e-mail afnog at afnog.org
To send a request to majordomo, e-mail majordomo at afnog.org and put
your request in the body of the message (i.e use "help" for help)

This list is maintained by owner-afnog at afnog.org