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

linux-ipsec: My FreeS/WAN 1.5 setup diary



I succesfully got my FreeS/WAN test network to work. I made a little diary
of it -- you can find it as an attachment to this email. Maybe someone has
use for it? 

Of course I'd appreciate all comments about my setup -- I might have done
something unnecessary and stupid :) But it's working!

Peter
This diary describes how I built a test network of two local nets and a 
"simulated" internet, and how I built a VPN between these local nets over 
the virtual internet. 

As an information source I used the book "Securing and Optimizing Linux 
v.1.3 RedHat Edition". It was for FreeSWAN 1.3 but almos everything in it 
was still up to date.


BUILDING THE TEST NET
=====================

Here is the geography of the test network and information about the 
machines I used:


----------
| JERSEY | local (right) client (win98 celeron laptop)
----------
  eth0 192.168.1.2
   |
   |
  eth1 192.168.1.1
-----------
| MOSKOVA | local (right) gateway and freeswan 1.5 server (redhat 6.2 p90)
-----------
  eth0 172.16.2.2
   |
   |
  eth0 172.16.2.1
--------
| JOLO | router (redhat 6.2 celeron)
--------
  eth1 172.16.1.1
   |
   |
  eth0 172.16.1.2
-----------
| OKINAWA | remote(left) gateway and freeswan 1.5 server (redhat 6.2 p100)
-----------
  eth1 10.1.2.1
   |
   |
  eth0 10.1.2.2
-------
| MMA | remote (left) client (redhat 6.2 p200)
-------


I wanted the 172.16.1.0 and 172.16.2.0 nets to simulate the public 
internet and the 10.1.2.0 and 192.168.1.0 to be private local networks. 

I created a /etc/hosts file for all RH boxes, which looked like this:

--snip--
jersey 192.168.1.2
moskova1 192.168.1.1
moskova0 172.16.2.2
jolo0 172.16.2.1
jolo1 172.16.1.1
okinawa0 172.16.1.2
okinawa1 10.1.2.1
--snip--

On RedHat machines I edited the /etc/sysconfig/network files, where I put 
information about gateways and the gateway interfaces. Here's a list of 
who is using which gateway and  using which interface:

mma's gw (eth0) is 10.1.2.1
okinawa's gw (eth0) is 172.16.1.1
moskova's gw (eth0) is 172.16.2.1
jersey's gw (eth0) is 192.168.1.1

For example mma's network file looked like this:

--snip--
NETWORKING=yes
HOSTNAME=mma
GATEWAY=10.1.2.1
GATEWAYDEV=eth0
--snip--

Jolo has no gateways as it is the place where the gateways are leading 
(the internet).

On Jersey I of course used Window's own network configuration utilities. 
The hosts file can be found on Win98 from the Windows directory where it 
is named as hosts.sam. You have to remove the .sam from the filename for 
it to work. 

On RH boxes I also configured the network interface cards by editing the 
/etc/sysconfig/network-scripts/ifcfg-ethX files where X is the number of 
the ethernet interface. Here's for example mma's ifcfg-eth0:

--snip--
DEVICE=eth0
BOOTPROTO=static
IPADDR=10.1.2.2
NETMASK=255.255.255.0
--snip--

To get routing enabled for moskova, jolo and okinawa I edited their 
/etc/sysctl.conf files to look like this:

--snip--
net.ipv4.ip_forward = 1
net.ipv4.conf.all.rp_filter = 0
net.ipv4.ip_always_defrag = 1
kernel.sysrq = 0
--snip--

Now the config files are ok. I restarted my network services on every 
machine with '/etc/rc.d/init.d/network restart'. 

For the VPN to work I added additional routes in moskova and okinawa to 
the remove private nets:

[root@moskova root]# route add -net 10.1.2.0 netmask 255.255.255.0 gw 
172.16.2.1

[root@mokinawa root]# route add -net 192.168.1.0 netmask 255.255.255.0 gw 
172.16.1.1

I also fetched from RedHat's site the update  for iputils 
(iputils-20001010-1.6x.i386.rpm)  because without it pinging  would fail 
to work for me. I now tested the  network from moskova with  'ping 
okinawa0'. mma cannot ping jersey or  vice  versa because they are on  
localnets and cannot see each other yet --  actually they can ping only  
their gateways at this moment, because jolo  doesn't know about the 
private  nets. You could of course at this point  setup masquerading 
firewalls on  moskova and okinawa to get mma and jersey  to ping the 
machines in the  internet we just created.


SETTING UP FREES/WAN IN MOSKOVA
===============================

I fetched the freeswan 1.5 tar ball and unpacked it in /usr/src. For 
getting freeswan to work we need to build a patched kernel for it so I 
grabbed the linux kernel 2.2.17 from my local mirror and unpacked it in
/usr/src also (first moving the old kernel sources away from 
/usr/src/linux). Then I compiled freeswan and inserted the freeswan code 
to the kernel source:

[root@moskova freeswan-1.5]# make insert
[root@moskova freeswan-1.5]# make programs
[root@moskova freeswan-1.5]# make install


Configuring and building the kernel
-----------------------------------

First I removed old asm, linux and scsi links from /usr/include. Then I 
made the new ones: 

[root@moskova linux]# ln -s /usr/src/linux/include/scsi /usr/include/scsi
[root@moskova linux]# ln -s /usr/src/linux/include/asm-i386 
/usr/include/asm
[root@moskova linux]# ln -s /usr/src/linux/include/linux 
/usr/include/linux

Then I ran 'make menuconfig' in /usr/src/linux and configured my kernel. I 
answered Y to all questions under Networking --> IPSec options 
(FreeS/WAN). I enabled routing, firewalling, masquerading, loopback device 
support and everything else I thought would be necessary for my server to run. My information 
source told me to not to disable "Kernel/User netlink socket" nor "Netlink 
device emulation" under "Network Options" and I believed it. Then I exited 
and saved my configuration and started compiling:

[root@moskova linux]# make dep; make clean; make bzImage

Now we have to move the kernel binary to the right place and fix some 
symbolic links:

[root@moskova linux]# rm /boot/vmlinuz
[root@moskova linux]# rm /boot/System.map
[root@moskova linux]# mv arch/i386/boot/bzImage /boot/vmlinuz-2.2.17
[root@moskova linux]# ln -s /boot/vmlinuz-2.2.17 /boot/vmlinuz
[root@moskova linux]# mv System.map /boot/System.map-2.2.17
[root@moskova linux]# ln -s /boot/System.map-2.2.17 /boot/System.map
[root@moskova linux]# mkinitrd /boot/initrd-2.2.17.img 2.2.17

Made and installed the kernel modules:

[root@moskova linux]# rm -fR /lib/modules/2.2.17/
[root@moskova linux]# make modules; make modules_install
[root@moskova linux]# depmod -a

I edited /etc/modules.conf where I put all the necessary information about 
the modules I need. For example I needed the driver for my 3COM's 3C590C 
network cards. Moskova's modules.conf looked like this:

alias parport_lowlevel parport_pc
alias eth0 3c59x
alias eth1 3c59x
alias sound-slot-0 es1371

And finally I edited /etc/lilo.conf for my liking and ran lilo after 
that with 'lilo -v'. Here's Moskova's lilo.conf (for example only, your 
setup may differ):

--snip--
boot=/dev/hda
map=/boot/map
install=/boot/boot.b
prompt
timeout=50
linear
default=linux

image=/boot/vmlinuz-2.2.16-3
        initrd=/boot/initrd-2.2.16-3.img
        label=linux-old
        read-only
        root=/dev/hda2

image=/boot/vmlinuz-2.2.17
        initrd=/boot/initrd-2.2.17.img
        label=linux
        read-only
        root=/dev/hda2
--snip--

After that I rebooted!


The Ipsec configuration files
-----------------------------

There are two config files for freeswan to work with. They are 
/etc/ipsec.sercrets and /etc/ipsec.conf. You may take a peek to look at 
them now. 

I made Moskova's /etc/ipsec.conf look like:

config setup
        interfaces="ipsec0=eth0"
        klipsdebug=none
        plutodebug=none
        plutoload=%search
        plutostart=%search

# sample connection
conn okinawa-moskova
        left=172.16.0.2
        leftsubnet=10.0.0.0/24
        leftnexthop=172.16.0.1
        right=172.16.9.2
        rightsubnet=10.0.3.0/24
        rightnexthop=172.16.9.1
        keyingtries=0
        auth=esp
        authby=rsasig

I created a shared key to be inserted in ipsec.secrets:

[root@moskova freeswan-1.5]# ipsec ranbits 256 >temp

I copied the contents of the temp file and pasted it into my ipsec.secrets 
and made it look like this:

--snip--
172.16.0.1 172.16.9.2
"0x50c570e3_e918c81e_98d81257_e7db3802_61655fc2_60802c77_61d1f9a7_660eb276"
--snip--

I removed the temp file after this.

As I want to use RSA I made the public keys like this:

[root@moskova freeswan-1.5]# ipsec rsasigkey --verbose 1023 >moskova-keys
[root@moskova freeswan-1.5]# ipsec rsasigkey --verbose 1023 >okinawa-keys

I pasted the lines starting with #pubkey= to my ipsec.conf file
leftrsasigkey (from okinawa-keys) and rightrsasigkey (from moskova-keys):

--snip--
config setup
        interfaces="ipsec0=eth0"
        klipsdebug=none
        plutodebug=none
        plutoload=%search
        plutostart=%search

# sample connection
conn okinawa-moskova
        left=172.16.0.2
        leftsubnet=10.0.0.0/24
        leftnexthop=172.16.0.1
        right=172.16.9.2
        rightsubnet=10.0.3.0/24
        rightnexthop=172.16.9.1
        keyingtries=0
        auth=ah
        authby=rsasig
leftrsasigkey=0x01037906285fd5b928416852b4d8ba468dfbc30612c232ce4b92780bbb762a4365b71ef54c57f721a76c61d382972a35c03360a59ef8a4b1f9f2488c1eafb9d34db26a777c555b9b5b3170d292318f0a03c7ce090c3444c7a3b07f8d467924ffd8d85b32374651dbff36d7096940e8ce171af413ddb4c99cb59137f746f4db8afe89
rightrsasigkey=0x010392e1752adbcd9bc25ffc8196add8d6dad8acb0a2f34b6b00a31685f0a9c62da40aed42d12724de5c23883724b20f3df77eecca06a1c962ca2ea71961b76bf85b9aa46477f50ea74f32a33a8af3228e801f757605a47361ba49deb711bfa2f0f03d19026e8bb9faf3ad2aa70f1642015e9fe0286b72ad32cd788dc80d0e76a7ff
        auto=start
--snip--

Then I copied the content of the moskova-keys file to my ipsec.secrets. It 
looks like this now:

--snip--
172.16.0.1 172.16.9.2
"0x50c570e3_e918c81e_98d81257_e7db3802_61655fc2_60802c77_61d1f9a7_660eb276"

: RSA   {
        # 1024 bits, Fri Nov  3 19:16:11 2000
        # for signatures only, UNSAFE FOR ENCRYPTION
       
#pubkey=0x010392e1752adbcd9bc25ffc8196add8d6dad8acb0a2f34b6b00a31685f0a9c62da40aed42d12724de5c23883724b20f3df77eecca06a1c962ca2ea71961b76bf85b9aa46477f50ea74f32a33a8af3228e801f757605a47361ba49deb711bfa2f0f03d19026e8bb9faf3ad2aa70f1642015e9fe0286b72ad32cd788dc80d0e76a7ff
        #IN KEY 0x4200 4 1
AQOS4XUq282bwl/8gZat2Nba2KywovNLawCjFoXwqcYtpArtQtEnJN5cI4g3JLIPPfd+7MoGocliyi6nGWG3a/hbmqRkd/UOp08yozqK8yKOgB91dgWkc2G6Sd63Eb+i8PA9GQJui7n6860qpw8WQgFen+Aoa3KtMs14jcgNDnan/w==
        # (0x4200 = auth-only host-level, 4 = IPSec, 1 = RSA)
        Modulus:
0x92e1752adbcd9bc25ffc8196add8d6dad8acb0a2f34b6b00a31685f0a9c62da40aed42d12724de5c23883724b20f3df77eecca06a1c962ca2ea71961b76bf85b9aa46477f50ea74f32a33a8af3228e801f757605a47361ba49deb711bfa2f0f03d19026e8bb9faf3ad2aa70f1642015e9fe0286b72ad32cd788dc80d0e76a7ff
        PublicExponent: 0x03
        # everything after this point is secret
        PrivateExponent:
0x61eba371e7de67d6eaa8566473e5e491e5c875c1f7879cab1764594b1bd973c2b1f381e0c4c33ee817b024c3215f7ea4ff4886af168641dc1f1a10ebcf9d503c0f12e1227c00fe7af45f775729376bc30d7c7c81e0cb6538ba0247616ad4c38096540de5e8942056a7b2aa92cf8ecc1fa4aab01a89684fb50409bdf4b0519a7b
        Prime1:
0xc86470207a511a3bf437550055ea01c14d5bf9666f2f4d94c91b7ab7f6e850fead0addb9bff6c8690c6a5b727a219187de64cba1e67cfd8332f0809c7ac6d18d
        Prime2:
0xbba3a2a3c0bc0f5acfdcb287df656b1a3ddec1dc6412fc5069bfd147a87b7ab0ae900fdbeee50208a5344bc064ca3da74a7b54a1be13bdbabf8eaa818b356ebb
        Exponent1:
0x85984ac0518b66d2a2cf8e003946abd63392a6444a1f890ddb67a7254f458b54735c93d12aa4859b5d9c3cf6fc1661053eeddd1699a8a90221f5ab12fc848bb3
        Exponent2:
0x7d17c1c2807d5f91dfe877053f98f2117e94813d980ca8359bd5362fc5a7a72074600a929f4356b06e22dd2aeddc291a31a78dc129627e7c7fb471abb2239f27
        Coefficient:
0x3976b2acf5141fdc988d8e45bccaf07e3444989ed5e0f3b09c718ebd05fcd3d9f96cf9d43978d65fbc989b7f31d4d81d968aa2a3d0b50268624a2e0be2717d3a
        }
# end
--snip--

That's it. Now it was time to configure the other freeswan server, 
Okinawa.

I compiled the 2.2.17 kernel and installed ipsec the same way as I did in 
Moskova. 

After that I copied the ipsec.conf and ipsec.secrets from Okinawa to 
Moskova. As they  were using the same interfaces for ipsec (eth0) I didn't 
have to change  anything in the ipsec.conf file. But in ipsec.secrets I of 
course had to  change RSA information which could be retriveved from the 
file  okinawa-keys I had created in Moskova. Okinawa's ipsec.secrets file 
looked like this:

--snip--
172.16.0.1 172.16.9.2
"0x50c570e3_e918c81e_98d81257_e7db3802_61655fc2_60802c77_61d1f9a7_660eb276"

: RSA   { 
        # 1024 bits, Fri Nov  3 19:11:43 2000
        # for signatures only, UNSAFE FOR ENCRYPTION
       
#pubkey=0x01037906285fd5b928416852b4d8ba468dfbc30612c232ce4b92780bbb762a4365b71ef54c57f721a76c61d382972a35c03360a59ef8a4b1f9f2488c1eafb9d34db26a777c555b9b5b3170d292318f0a03c7ce090c3444c7a3b07f8d467924ffd8d85b32374651dbff36d7096940e8ce171af413ddb4c99cb59137f746f4db8afe89
        #IN KEY 0x4200 4 1
AQN5Bihf1bkoQWhStNi6Ro37wwYSwjLOS5J4C7t2KkNltx71TFf3IadsYdOClyo1wDNgpZ74pLH58kiMHq+5002yand8VVubWzFw0pIxjwoDx84JDDREx6Owf41GeST/2NhbMjdGUdv/NtcJaUDozhca9BPdtMmctZE390b024r+iQ==
        # (0x4200 = auth-only host-level, 4 = IPSec, 1 = RSA)
        Modulus:
0x7906285fd5b928416852b4d8ba468dfbc30612c232ce4b92780bbb762a4365b71ef54c57f721a76c61d382972a35c03360a59ef8a4b1f9f2488c1eafb9d34db26a777c555b9b5b3170d292318f0a03c7ce090c3444c7a3b07f8d467924ffd8d85b32374651dbff36d7096940e8ce171af413ddb4c99cb59137f746f4db8afe89
        PublicExponent: 0x03
        # everything after this point is secret
        PrivateExponent:
0x50aec59539261ad6458c78907c2f095282040c8177343261a55d27a41c2cee7a14a3883aa4c11a484137ac64c6ce8022406e69fb1876a6a185b2bf1fd1378920ac25be2547abe97a11ee4701a3617bc5fe7c9d523ba0f18854f4366aa2dfa5643d3ad6e515ff26806aefa169f1106838b964048c2354525b881d8cbf2efab40b
        Prime1:
0xda5c17f2c79251f625e2ae46a0d6bc792136aa032f97b5cdd168d9a8e3795715e63f42efd0d51b1d80cd8bd23ca2f21bca9fd9333eedb9fb317d8a0adf977fbd
        Prime2:
0x8de2c72aa8872b04300a796879210da5af177635bbbe83962eb61b304d3709ac191ab1fee0082a58b5d46b4fc29288aa135dfdaf55b0800cba4d69cb357b70bd
        Exponent1:
0x9192baa1da618bf96e971ed9c08f2850c0cf1c021fba7933e0f0911b4250e4b9442a2c9fe08e1213ab33b28c286ca167dc6a90ccd49e7bfccba906b1ea64ffd3
        Exponent2:
0x5e972f71c5af7202cab1a645a61609191f64f97927d457b97479677588cf5bc810bc76a9eab01c3b23e2f2352c61b071623ea91f8e75aab326de468778fcf5d3
        Coefficient:
0x4fd954347c830e14704cde1f2514e3c8be5e0baf734e2b8550ac13f2b4df79d16c8fd42ce19dab62d6bee3855915ff47bed737f13d62404f8941a9c2e356cd91
        }
#end
--snip--

After that I rebooted both gateways and watached how on boot both 
of my freeswan servers negotiated with eachother and started my VPN. After 
the servers were up I could ping from jersey to mma and vice versa. I ran 
'tcpdump' on Jolo and saw that the traffic was encrypted (only traffic 
from ports 50 and 51 was to be seen). 

For testing purposes I found convient to remove the ipsec service from the 
list of automatically started services at boot (just use the 'setup' 
command and choose "System Services" and unselect ipsec with hitting 
space) and to start and stop it using the commands '/etc/rc.d/init.d/ipsec 
start' and '/etc/rc.d/init.d/ipsec stop'. 

As I wanted mma and jersey to bee in the same Windows workgroup I started 
WINS in mma using Samba. I defined the WINS server's ip address in jersey 
and soon (after reboot and a few minutes waiting) I could see mma in 
jersey's Network neighborhood. 


IPCHAINS FIREWALL
=================

I wanted my both private nets to be behind a masquerading firewall. 
Natural choice for me was to build an ipchains script which would provide 
me this. As I'm no guru with ipchains I first tried to use the one that is 
specified in the book "Securing and Optimizing Linux" but couldn't get it 
working. So I asked my friend to build me a working script. Here's the 
result, a working ipchains script for moskova:

--snip--
#!/bin/bash

#--------------------------------------------------
# Variables
#--------------------------------------------------

PATH=/sbin:/usr/sbin

ETH0IP=172.16.2.2
ETH1IP=192.168.1.1

GOODIF=eth1
GOODIP=192.168.1.1
BADIF=eth0
BADIP=172.16.2.2

ETH0MASK=255.255.255.0
ETH1MASK=255.255.255.0

NATNET=192.168.1.0/255.255.255.0

DEFGW=172.16.2.1

ANYWHERE=0.0.0.0/0
IPSECSG=172.16.1.2
FREESWANIF=ipsec0
REMOTEGOOD=10.1.2.0/24

#---------------------------------------------
# Preparations
#---------------------------------------------

# Remove old chains
ipchains -F
ipchains -X

# Secure the execution of this script. Removed in the end.
ipchains -I input 1 -j DENY
ipchains -I output 1 -j DENY
ipchains -I forward 1 -j DENY

# Define the chains between networks
ipchains -N good-bad
ipchains -N bad-good

# Enable loopback device usage
ipchains -A input -i lo -s 0/0 -d 0/0 -j ACCEPT
ipchains -A output -i lo -s 0/0 -d 0/0 -j ACCEPT

#--------------------------------------------------------------------
# ICMP
#--------------------------------------------------------------------

# let's create the icmp-acc chain where we define the icmp rules
ipchains -N icmp-acc
ipchains -A icmp-acc -p icmp --icmp-type destination-unreachable -j ACCEPT 
ipchains -A icmp-acc -p icmp --icmp-type parameter-problem -j ACCEPT 
ipchains -A icmp-acc -p icmp --icmp-type source-quench -j ACCEPT
ipchains -A icmp-acc -p icmp --icmp-type time-exceeded -j ACCEPT


#---------------------------------------------------------------------
# Chains for interfaces
#----------------------------------------------------------------------

# create the chains bad-if and good-if
ipchains -N bad-if
ipchains -N good-if

# 
ipchains -A input -i $FREESWANIF -s $ANYWHERE -d $ANYWHERE -j ACCEPT
ipchains -A input -d $BADIP -j bad-if
ipchains -A input -d $GOODIP -j good-if

ipchains -A output -i $FREESWANIF -s $ANYWHERE -d $ANYWHERE -j ACCEPT

#
# bad-if
#

# ssh
ipchains -A bad-if -p TCP ! -y --sport ssh -j ACCEPT
ipchains -A bad-if -p UDP --sport ssh -j ACCEPT

# masq replies
ipchains -A bad-if -p TCP --dport 61000:65096 -j ACCEPT
ipchains -A bad-if -p UDP --dport 61000:65096 -j ACCEPT

# icmp
#ipchains -A bad-if -j icmp-acc
ipchains -A bad-if -p ICMP --icmp-type pong -j ACCEPT
ipchains -A bad-if -p udp -s $IPSECSG -j ACCEPT
ipchains -A bad-if -p 50 -s $IPSECSG -j ACCEPT
ipchains -A bad-if -p 51 -s $IPSECSG -j ACCEPT
ipchains -A bad-if -j DENY -l

#
# good-if
#

ipchains -A good-if -i ! $GOODIF -j DENY -l

# icmp
ipchains -A good-if -j icmp-acc

# proxy
ipchains -A good-if -p tcp --dport 3005 -j ACCEPT
ipchains -A good-if -p udp --dport 3005 -j ACCEPT

# http
ipchains -A good-if -p tcp ! -y --sport 80 -j ACCEPT
ipchains -A good-if -p udp --sport 80 -j ACCEPT

# ssh
ipchains -A good-if -p tcp --sport ssh -j ACCEPT
ipchains -A good-if -p udp --sport ssh -j ACCEPT
ipchains -A good-if -p tcp --dport ssh -j ACCEPT
ipchains -A good-if -p udp --dport ssh -j ACCEPT

ipchains -A good-if -p udp -s $IPSECSG -j ACCEPT
ipchains -A good-if -p 50 -s $IPSECSG -j ACCEPT
ipchains -A good-if -p 51 -s $IPSECSG -j ACCEPT

ipchains -A good-if -j DENY -l

#-------------------------------------------------------------
# rp filtering
#-------------------------------------------------------------

# rp filtering is bad for ipsec
echo 0 > /proc/sys/net/ipv4/conf/$BADIF/rp_filter
echo 0 > /proc/sys/net/ipv4/conf/$FREESWANIF/rp_filter

# forward anything from the freeswan virtual if ipsec tunnel
#---------------------------------------------------------------------
# Forwarding and masq modules

echo "1" > /proc/sys/net/ipv4/ip_forward
modprobe ip_masq_ftp
modprobe ip_masq_raudio
ipchains -M -S 3600 10 50

ipchains -A forward -i $FREESWANIF -s $ANYWHERE -d $ANYWHERE -j ACCEPT -l
ipchains -A forward -s $REMOTEGOOD -d $NATNET -i $GOODIF -j ACCEPT -l
ipchains -A forward -s $NATNET -i $BADIF -j good-bad -l
ipchains -A forward -i $GOODIF -j bad-good -l
ipchains -A forward -j DENY -l

# Allow all tcp udp imcp good-bad. Masquerade.
ipchains -A good-bad -j MASQ -l

# Deny all nonmasqueraded from bad to good. Log.
ipchains -A bad-good -j DENY -l

#-----------------------------------------------------------------
# The final touch
#-----------------------------------------------------------------

# Remove the blocks that we defined in the beginning
ipchains -D input 1
ipchains -D output 1
ipchains -D forward 1
--snip--

That's it! Time for a cup of coffee...


Follow-Ups: References: