[OpenBSDsupport]

OpenBSD Firewall / VPN using IPsec (site-to-site)

OpenBSD Firewall / VPN using IPsec (site-to-site)

This document will guide you through a very simple site-to-site VPN setup.
A lot of the same information can be found in the vpn(8) manual.

A few assumptions will be made here:

	* You are using OpenBSD as the Firewall / Gateway / VPN endpoint at each site.
	* Each box has two interfaces (int_if & ext_if).
	* The "Authentication=" passphrase in both isakmpd.conf files match.
	* 1 Static Public IP address and 1 Static Private IP address are assigned to each box.
	
	* Machine A has the following IP addresses:
		* Public  = A.B.C.D
		* Private = 10.1.1.1    (10.1.1.0 Network)
		
	* Machine B has the following IP addresses:
		* Public  = W.X.Y.Z
		* Private = 192.168.1.1 (192.168.1.0 Network)

---------------------------------------------------------------------------

AUTOMATED KEYING USING PRE-SHARED SECRETS

1.  Create /etc/isakmpd/isakmpd.conf for machine A (change W.X.Y.Z and Authentication= accordingly):

# Incoming phase 1 negotiations are multiplexed on the source IP
# address. Phase 1 is used to set up a protected channel just
# between the two gateway machines. This channel is then used for
# the phase 2 negotiation traffic (i.e. encrypted & authenticated).

[Phase 1]
W.X.Y.Z=            peer-machineB

# 'Phase 2' defines which connections the daemon should establish.
# These connections contain the actual "IPsec VPN" information.

[Phase 2]
Connections=            VPN-A-B

# ISAKMP phase 1 peers (from [Phase 1])

[peer-machineB]
Phase=                  1
Transport=              udp
Address=                W.X.Y.Z
Configuration=          Default-main-mode
Authentication=         change_this_to_your_secret

# IPSEC phase 2 connections (from [Phase 2])

[VPN-A-B]
Phase=                  2
ISAKMP-peer=            peer-machineB
Configuration=          Default-quick-mode
Local-ID=               machineA-internal-network
Remote-ID=              machineB-internal-network

# ID sections (as used in [VPN-A-B])

[machineA-internal-network]
ID-type=                IPV4_ADDR_SUBNET
Network=                10.1.1.0
Netmask=                255.255.255.0

[machineB-internal-network]
ID-type=                IPV4_ADDR_SUBNET
Network=                192.168.1.0
Netmask=                255.255.255.0

# Main and Quick Mode descriptions (as used by peers and connections)

[Default-main-mode]
DOI=                    IPSEC
EXCHANGE_TYPE=          ID_PROT
Transforms=             3DES-SHA,BLF-SHA

[Default-quick-mode]
DOI=                    IPSEC
EXCHANGE_TYPE=          QUICK_MODE
Suites=                 QM-ESP-3DES-SHA-SUITE

2.  chmod 600 /etc/isakmpd/isakmpd.conf for machine A

3.  Create /etc/isakmpd/isakmpd.conf for machine B (change A.B.C.D and Authentication= accordingly):

# Incoming phase 1 negotiations are multiplexed on the source IP
# address. Phase 1 is used to set up a protected channel just
# between the two gateway machines. This channel is then used for
# the phase 2 negotiation traffic (i.e. encrypted & authenticated).

[Phase 1]
A.B.C.D=          peer-machineA

# 'Phase 2' defines which connections the daemon should establish.
# These connections contain the actual "IPsec VPN" information.

[Phase 2]
Connections=            VPN-B-A

# ISAKMP phase 1 peers (from [Phase 1])

[peer-machineA]
Phase=                  1
Transport=              udp
Address=                A.B.C.D
Configuration=          Default-main-mode
Authentication=         change_this_to_your_secret

# IPSEC phase 2 connections (from [Phase 2])

[VPN-B-A]
Phase=                  2
ISAKMP-peer=            peer-machineA
Configuration=          Default-quick-mode
Local-ID=               machineB-internal-network
Remote-ID=              machineA-internal-network

# ID sections (as used in [VPN-A-B])

[machineA-internal-network]
ID-type=                IPV4_ADDR_SUBNET
Network=                10.1.1.0
Netmask=                255.255.255.0

[machineB-internal-network]
ID-type=                IPV4_ADDR_SUBNET
Network=                192.168.1.0
Netmask=                255.255.255.0

# Main and Quick Mode descriptions (as used by peers and connections)

[Default-main-mode]
DOI=                    IPSEC
EXCHANGE_TYPE=          ID_PROT
Transforms=             3DES-SHA,BLF-SHA

[Default-quick-mode]
DOI=                    IPSEC
EXCHANGE_TYPE=          QUICK_MODE
Suites=                 QM-ESP-3DES-SHA-SUITE

4.  chmod 600 /etc/isakmpd/isakmpd.conf for machine B

5.  Create the same /etc/isakmpd/isakmpd.policy for both machine A and machine B:

Keynote-version: 2
Authorizer: "POLICY"
Conditions: app_domain == "IPsec policy" &&
            esp_present == "yes" &&
            esp_enc_alg != "null" -> "true";

6.  chmod 600 /etc/isakmpd/isakmpd.policy for both machine A and machine B

7.  Create /etc/pf.conf for machine A (change macros accordingly):

# macros
int_if = "fxp0"
ext_if = "fxp1"

icmp_types = "{ echorep, echoreq, timex, unreach }"

# GATEWAY_A = Machine A External IP
# GATEWAY_B = Machine B External IP
# NETWORK_A = Machine A Internal Network
# NETWORK_B = Machine B Internal Network
GATEWAY_A = "A.B.C.D/32"
GATEWAY_B = "W.X.Y.Z/32"
NETWORK_A = "10.1.1.0/24"
NETWORK_B = "192.168.1.0/24"

# scrub
scrub in all

# nat/rdr
nat on $ext_if from $int_if:network to any -> $ext_if

# filter rules
block in log on { enc0, fxp1 } all
block out on { enc0, fxp1 } all

pass quick on lo0 all

pass in on $ext_if inet proto icmp from any to $ext_if icmp-type $icmp_types keep state

pass in  on $int_if from $int_if:network to any keep state
pass out on $int_if from any to $int_if:network keep state

pass out on $ext_if proto tcp all modulate state
pass out on $ext_if proto { udp, icmp } all keep state

# VPN Rules
# Passing in encrypted traffic from security gateways
pass in  quick on $ext_if proto esp from $GATEWAY_B to $GATEWAY_A
pass out quick on $ext_if proto esp from $GATEWAY_A to $GATEWAY_B

# Need to allow ipencap traffic on enc0.
pass in  quick on enc0 proto ipencap all

# Passing in traffic from the designated subnets.
pass in  quick on enc0 from $NETWORK_B to $NETWORK_A
pass out quick on enc0 from $NETWORK_A to $NETWORK_B

# Passing in isakmpd(8) traffic from the security gateways
pass in  quick on $ext_if proto udp from $GATEWAY_B to $GATEWAY_A port isakmp
pass out quick on $ext_if proto udp from $GATEWAY_A to $GATEWAY_B port isakmp

8.  Create /etc/pf.conf for machine B (change macros accordingly):

# macros
int_if = "fxp0"
ext_if = "fxp1"

icmp_types = "{ echorep, echoreq, timex, unreach }"

# GATEWAY_B = Machine B External IP
# GATEWAY_A = Machine A External IP
# NETWORK_B = Machine B Internal Network
# NETWORK_A = Machine A Internal Network
GATEWAY_B = "W.X.Y.Z/32"
GATEWAY_A = "A.B.C.D/32"
NETWORK_B = "192.168.1.0/24"
NETWORK_A = "10.1.1.0/24"

# scrub
scrub in all

# nat/rdr
nat on $ext_if from $int_if:network to any -> $ext_if

# filter rules
block in log on { enc0, fxp1 } all
block out on { enc0, fxp1 } all

pass quick on lo0 all

pass in on $ext_if inet proto icmp from any to $ext_if icmp-type $icmp_types keep state

pass in  on $int_if from $int_if:network to any keep state
pass out on $int_if from any to $int_if:network keep state

pass out on $ext_if proto tcp all modulate state
pass out on $ext_if proto { udp, icmp } all keep state

# VPN Rules
# Passing in encrypted traffic from security gateways
pass in  quick on $ext_if proto esp from $GATEWAY_A to $GATEWAY_B
pass out quick on $ext_if proto esp from $GATEWAY_B to $GATEWAY_A

# Need to allow ipencap traffic on enc0.
pass in  quick on enc0 proto ipencap all

# Passing in traffic from the designated subnets.
pass in  quick on enc0 from $NETWORK_A to $NETWORK_B
pass out quick on enc0 from $NETWORK_B to $NETWORK_A

# Passing in isakmpd(8) traffic from the security gateways
pass in  quick on $ext_if proto udp from $GATEWAY_A to $GATEWAY_B port isakmp
pass out quick on $ext_if proto udp from $GATEWAY_B to $GATEWAY_A port isakmp

9.  Uncomment #net.inet.ip.forwarding=1 in /etc/sysctl.conf on both machine A and machine B

10. Add the following in /etc/rc.conf.local on both machine A and machine B:

isakmpd_flags=""
pf=YES

11. Add routing information 
    To make the changes persistent please add the following to /etc/rc.local so it will
    take effect on boot up.

    machine A :
    route add -net W.X.Y A.B.C.D

    machine B :
    route add -net A.B.C W.X.Y.Z

12. Reboot both machines

TESTING CONNECTIVITY / SECURITY

13. Simple ping test

	- From any client on NETWORK_A, ping any alive host on NETWORK_B
	- From any client on NETWORK_B, ping any alive host on NETWORK_A

14. The ping fails, we need to add route information to the clients.

    OpenBSD Client on network A:
    add to /etc/rc.local

    route add -net W.X.Y A.B.C.D

    RedHat Client on network A:
    add to /etc/rc.local

    route add -net W.X.Y.0 netmask 255.255.255.0 gw A.B.C.D

    Windows Client on network A:
    run at a command prompt 

    route -p add W.X.Y.0 mask 255.255.255.0 A.B.C.D

    Clients on the B network would require the same changes but swap
    the W.X.Y with A.B.C and A.B.C.D with W.X.Y.Z

	
15. Run netstat -r on both machines, you should see a similar output as this under the "Encap:" section:

- Machine A:

Encap:
Source             Port  Destination        Port  Proto SA(Address/Proto/Type/Direction)
192.168.1/24       0     10.1.1/24          0     0     W.X.Y.Z/50/use/in
10.1.1/24          0     192.168.1/24       0     0     W.X.Y.Z/50/require/out

- Machine B:

Encap:
Source             Port  Destination        Port  Proto SA(Address/Proto/Type/Direction)
10.1.1/24          0     192.168.1/24       0     0     A.B.C.D/50/use/in
192.168.1/24       0     10.1.1/24          0     0     A.B.C.D/50/require/out

16. Run tcpdump -i enc0 , you should see a similar output when pinging hosts on the opposite network:

- Client behind machine A pinging client behind machine B [Note the (authentic,confidential) and (encap)]:

09:59:12.550519 (authentic,confidential): SPI 0xae955d33: 10.1.1.106 > 192.168.1.3: icmp: echo request (encap)
09:59:12.601795 (authentic,confidential): SPI 0x4e0409e9: 192.168.1.3 > 10.1.1.106: icmp: echo reply (encap)

- Client behind machine B pinging client behind machine A [Note the (authentic,confidential) and (encap)]:

09:59:13.540813 (authentic,confidential): SPI 0xae955d33: 192.168.1.3 > 10.1.1.106: icmp: echo request (encap)
09:59:13.638618 (authentic,confidential): SPI 0x4e0409e9: 10.1.1.106 > 192.168.1.3: icmp: echo reply (encap)

17. Finished

Joel Gudknecht
photohaus@gmail.com
20041122

Kevin Rakos (edited)
30JAN2009