Setting up a FreeBSD IPSec Tunnel
This article was written by John J. Rushford Jr.
jjr@alisa.org
Last modified 5/26/01
See also this ONLamp article.
Introduction
Recently I was approached by a friend that has a scanning and imaging
business focused on imaging legal documents for large law firms.
He has two offices one located in Denver Colorado and another in the
suburb of Broomfield Colorado. His goal was to establish networking
between these two offices so that Microsoft file sharing, print sharing
and network neighborhood browsing are fully functional between the
two offices at a reasonable cost. In addition, he wished to have a
web server and an email server to promote his business.
To meet his requirements, I chose high speed DSL connections to the
internet with the local phone company using their business class DSL
service. The business class DSL service is low cost, roughly $100.00
per month, and provides 5 leased public static IP addresses with
network bandwidth of 1 Mbits up and down.
For his two subnets, I chose two machines running FreeBSD 4.2-STABLE
as firewall gateway machines for the two private subnets being built.
In addition to the firewall functionality, the FreeBSD machines would
act as his web server, mail server, and as a Samba server (see
Figure 1). The gateway designated bsd1 would act as the
primary domain controller for Windows, primary WINS server, and Windows master browser
for the MS domain we shall call scanningcomp.
In the remainder of this document, bsd1 refers to the
FreeBSD 4.2 machine with the private IP address 192.168.1.254
and bsd2 refers to the FreeBSD 4.2 machine with the
private IP address 192.168.2.254. These private IP’s are used to
configure all private subnet services. The public IP’s are only
only used with external DNS registration and for connecting
the endpoints of the VPN. For purposes of this document, the public
IP addresses are 172.16.1.254 and 172.17.1.254.
Figure 1
DSL Internet connection Setup
The telephone company setup the DSL connections at both sites and
the domain name scanningcomp.com was registered with the
telephone company’s primary and secondary DNS servers using
the leased static IP addresses. The Cisco DSL modems were
programmed in PPP mode using the instructions from the telephone
company and connected to the public network interface, rl0, on
both FreeBSD machines, bsd1 and bsd2. In the
/etc/rc.conf file, the leased static IP addresses and
netmask were configured and everything verified to insure proper
operation.
Microsoft networking setup
In order to facilitate Microsoft network browsing, file sharing, and
printer sharing between the two subnets, both FreeBSD machines
were loaded with Samba 2.0.7. The machines were not configured
to share any part of their disks but, only to provide network logins,
WINS services, and the synchronization of browse lists accross the
two subnets 192.168.1.0 and 192.168.2.0. bsd1 was configured as
the primary domain controller and as the WINS server for
both subnets. bsd2 was configured as the master browser
for its subnet and as a proxy WINS server with the
WINS server pointed at bsd1.
All the Windows PC’s were configured to obtain their IP addresses
from bsd1 or bsd2 as appropriate using the DHCP
server loaded on the two FreeBSD machines. The DHCP
servers were configured only to run on the private network interfaces
and in addition to providing the IP address to a PC it also provides
the respective default route, the domain-name, the
domain-name-servers (which are bsd1 at 192.168.1.254
and bsd2 at 192.168.2.254), broadcast-address, and
netbios-name-servers 192.168.1.254.
bsd1 was configured to be the mail server for the domain with
the appropriate DNS MX record set in the telephone companies
DNS servers. Microsoft Outlook on all PC’s is set to use
bsd1, 192.168.1.254, as the SMTP and POP3 server.
/usr/ports/mail/qpopper was loaded and configured on bsd1
Also, named was configured on both machines to provide DNS
services where forwarding to the telephone companies DNS servers is
used. Both bsd1 and bsd2 act as the primary DNS server
for 1.168.192.in-addr.arpa and 2.168.192.in-addr.arpa as well as
the domain name scanningcomp.com so that bsd1 may resolve
and allow mail relaying from the PC’s. The Cw flag was set
in /etc/mail/sendmail.cf to scanningcomp.com and The
/etc/mail/sendmail.cw file was also set to scanningcomp.com.
Managing user ids and other servers is done with Webmin which is
loaded only on bsd1. The user id module on Webmin is
configured so that the smbpasswd is set along with the unix
password so that the two passwords are synchronized.
FreeBSD 4.2-STABLE kernel configuration
Both FreeBSD machines are configured as firewalls for their
respective subnets and are configured for IPSec required for the
IPSec tunnel. The relevant kernel configuration options
used are:
# IP security (crypto; define w/ IPSEC) options IPSEC options IPSEC_ESP options IPSEC_DEBUG # Generic tunnel interface pseudo-device gif 4 # Berkeley packet filter used by dhcp server. pseudo-device bpf 4 # Firewall flags options IPFIREWALL options IPDIVERT options IPFILTER options IPFILTER_LOG
In enabling the firewall the following relevent options are set
in the /etc/rc.conf file:
gateway_enable="YES" defaultrouter="172.x.1.110" # assigned by the telephone company firewall_enable="YES" firewall_type="open" natd_enable="YES" natd_interface="rl0" named_enable="YES"
FreeBSD 4.2-STABLE IPSec tunnel configuration
In order to provide for automatic IPSec key exchange between
the two FreeBSD machines, you must load the port
/usr/ports/security/racoon provide a configuration
file (/usr/local/etc/racoon/racoon.conf), key file
(/usr/local/etc/racoon/psk.txt), and start the
/usr/local/sbin/racoon daemon at boot time.
I found that I did not have to modify the default configuration
file so, I left /usr/local/etc/racoon.conf untouched.
I edited the key file, /usr/local/etc/racoon/psk.txt, and installed
my private encryption keys:
# /usr/local/etc/racoon/psk.txt # IPv4/v6 addresses # 192.168.1.254 foobar 192.168.2.254 foobar
The key file must be protected and set to mode 0600 otherwise
racoon will not run:
# chown root.wheel /usr/local/etc/racoon/psk.txt # chmod 0600 /usr/local/etc/racoon/psk.txt
To automatically start racoon at boot time, I created the
/etc/rc.local startup script with the following:
#!/bin/sh # # /etc/rc.local # # dhcp server if [ -x /usr/local/sbin/dhcpd ]; then echo -n "dhcpd " /usr/local/sbin/dhcpd -cf /etc/dhcpd.conf rl1 fi # webmin server if [ -x /etc/webmin/start ]; then echo -n "webmin " /etc/webmin/start fi # racoon key exchange server if [ -x /usr/local/sbin/racoon ]; then echo -n "racoon " /usr/local/sbin/racoon -f /usr/local/etc/racoon/racoon.conf fi
To make the IPSec tunnel connection and to add the route
between the two private subnets, I wrote the following shell
script and installed it at /usr/local/etc/rc.d/tunnel.sh
WARNING: The shell script shown here has been formatted
for this web page, click
here to
download this script:
#!/bin/sh # BSD1_IP="192.168.1.254" BSD1_PUB_IP="172.16.1.254" BSD1_NET="192.168.1.0/24" BSD2_IP="192.168.2.254" BSD2_PUB_IP="172.17.1.254" BSD2_NET="192.168.2.0/24" GIF0="gif0 inet" GIFCONFIG="/usr/sbin/gifconfig" IFCONFIG="/sbin/ifconfig" HOSTNAME=`/bin/hostname` NETMASK="255.255.255.0" echo "\nStarting ipsec tunnel... " case $HOSTNAME in bsd1.scanningcomp.com) $GIFCONFIG $GIF0 $BSD1_PUB_IP $BSD2_PUB_IP $IFCONFIG $GIF0 $BSD1_IP $BSD2_IP $NETMASK /usr/sbin/setkey -FP /usr/sbin/setkey -F /usr/sbin/setkey -c << EOF spdadd $BSD1_NET $BSD2_NET any -P out ipsec esp/tunnel/${BSD1_IP}-${BSD2_IP}/require; spdadd $BSD2_NET $BSD1_NET any -P in ipsec esp/tunnel/${BSD2_IP}-${BSD1_IP}/require; EOF /sbin/route add $BSD2_NET $BSD1_IP ;; bsd2.scanningcomp.com) $GIFCONFIG $GIF0 $BSD2_PUB_IP $BSD1_PUB_IP $IFCONFIG $GIF0 $BSD2_IP $BSD1_IP $NETMASK /usr/sbin/setkey -FP /usr/sbin/setkey -F /usr/sbin/setkey -c << EOF spdadd $BSD2_NET $BSD1_NET any -P out ipsec esp/tunnel/${BSD2_IP}-${BSD1_IP}/require; spdadd $BSD1_NET $BSD2_NET any -P in ipsec esp/tunnel/${BSD1_IP}-${BSD2_IP}/require; EOF /sbin/route add $BSD1_NET $BSD2_IP ;; esac
It is important to note that the endpoints of this tunnel are
192.168.1.254 and 192.168.2.254. No broadcast traffic may be
passed between the subnets. This was important in that when
configuring Samba, you have to use the IP address of the Samba
server and you may not use the broadcast IP address for things
like remote_announce.
In Conclusion
I hope that this web page proves useful to those that read it.
I believe that I have been complete and that there are no
errors or omissions. If you find any errors, omissions or
mistakes, please let me know so that I may update this page
with corrections.
References
- "Teach Yourself Samba in 24 Hours"; by
Gerald Carter with Richard Sharpe; Sams, 1999;
ISBN 0-672-31609-9. - "The Complete FreeBSD"; by Greg Lehey;
Walnut Creek CDROM, 1999; ISBN 1-57176-246-9.
The script, as provided, results in a "no route to host" error when establishing the IPSec tunnel.
Changing $BSD[12]_IP to $BSD[12]_PUB_IP in the spdadd lines results in a tunnel being established, however I get a "no route to host" when trying to ping through the tunnel.
One thing I noticed with all implementations using local/private IPs is that there will always be a routing issue. Since we are using "non-routable" addresses, I usually have to make manual entries in the routing table just to allow the subnets to pass packets to each other.
Does this configuration result in 3 IP headers?
Normally, when IPsec is used with gif, IPsec _transport_ mode is used. The result is 2 an (outer/gif) IP header for the gif tunnel and the original IP header protected by IPsec.
In this example, IPsec tunnel mode is used.
IPsec tunnel mode creates its own second IP header, while transport mode will not. Using gif, which itself creates an outer IP header, should create a 3rd IP header.
Well, I was struggling with something similar until I saw an article in daemonnews which said that the gif device was needed for tunnel mode but *not* for transport mode…
I’m trying to connect to a network behind a hardware VPN gateway. So far I have got tunnel built, and I can send packets through it but I get nothing back. I’d think it was routing but other people (using Linux and freeswan) have it working fine.
Jim
"The Cw flag was set in /etc/mail/sendmail.cf to scanningcomp.com and The /etc/mail/sendmail.cw file was also set to scanningcomp.com."
Note the "AND". Is this really necessary to do both?
From http://www.sendmail.org/faq/section4.html,
". Add domain.net to /etc/mail/local-host-names [known as /etc/sendmail.cw prior to version 8.10] (if you are using FEATURE(`use_cw_file’)) or add "Cw domain.net" to your configuration file."
Note the "OR".
I’m guessing that the default cf in fbsd will read the cw file. so that’s all you need to change.
No, it is not necessary to set both.
I’ve been banging my head along with out IT guy trying to get my FreeBSD box to authenticate with a Cisco PIX firewall device. It is attempting to connect, but seems to fail somwhere during phase I authentication. It doesn’t seem to know when/how to send the proper
key information. If anyone has done this and would be willing
to give some advice, please let me know.
I’m using FreeBSD 4.4 with the latest port of racoon (20011026a).
I have all the IPSEC* options in the kernel.
I’ve tried various combinations in the remote and sainfo sections with the same results.
thanks in advance,
jpc
Hello,
Do you have an documents on how to do this or can you point me in the fight direction?
I have a PIX in our HQ office and I want to install a FreeBSD server in our remote office to create a VPN between them.
Thanks in advance,
Rob
I was confused about this line:
$IFCONFIG $GIF0 $BSD2_IP $BSD1_IP $NETMASK
Which of the two networks does the netmask apply to? If
the two private networks had different sized netmasks, how
should this be specified?
(to be honest I’m confused about why the gif device is needed at all, but an article in daemonnews said it was to make the routing work properly when using tunnel mode, and there were other ways to do it – but they didn’t elaborate on what they were)
Jim
Greetings,
In my situation we used 192.168.1.x and 192.168.2.x on the private networks. Both private networks have the same netmask, 255.255.255.0 so I only defined one netmask variable and used it in both switches of the case statement. If one has private networks with differing netmasks the script is easily modifable to fit the need.
Keep in mind that the script is executed on both machines as appropriate through the case statement and the netmask determines how to route to the remote network.
With FreeBSD 4.4, this article is now out of date. I’ll get it updated soon. In the script, I am using gifconfig to setup the gif interface. This is no-longer required with FreeBSD 4.4 and gif interface devices are now configured dynamically.
If you use the script, delete or comment out all lines that
have $GIFCONFIG and edit /etc/rc.conf with the proper
configuration. See /etc/defaults/rc.conf for details.
For example:
# /etc/rc.conf
gif_interfaces="gif0"
gifconfig_gif0="172.16.1.254 172.17.1.254"
If you’d like to keep the tunnel creation as part of the tunnel.sh script you can also handle that like:
ifconfig gif0 create tunnel a.b.c.d e.f.g.h
-Mark
On the ifconfig statements in the tunnel.sh script, you have left off the "netmask" keyword before the "$NETMASK" variable. You could either add "netmask" before "$NETMASK" or you could define "NETMASK="netmask 255.255.255.0". Without this change, the gif0 device gets incorrectly set.
Gary Burchett
We have four nodes,we want to use ipsec to create our own vpn?
can it support?
Perhaps you should be asking your help questions in the Support Forum. Click on Forums, top right corner of the page.
Just saw your comment. I have not tried to support more
than 2 nodes. However, I see no reason why you should
not be able to support 4. You’ll use more gif interfaces ie,
two in each host at least or perhaps three if you intend to
create a route from one to the other 3 as in a complete
graph on four vertices.
I need to update this page though. I hope you know that
there have been changes with respect to configuring gif
since 4.2.