Linux 2.6 Kernel IPsec VPN

OBJECTIVES

Configure a transport mode IPsec VPN partner

Configure a tunnel mode IPsec VPN partner

Implement pre-shared-key or certificate based partner authentication

Configure iptables rules to permit IPsec partner communications

Configure iptables to firewall packets emerging from an IPsec tunnel

Know how to use setkey and ethereal/tcpdump to check IPsec VPN status

PREPARATION

Install ipsec-tools

I recommend kernel-2.6.6-1.435.2.3 and ipsec-tools-0.2.5-4 because an issue with setkey deleting SPD entries is resolved.

I also recommend initscripts 7.55.1-1 because a bug in ifup-ipsec which set both esp and ah requirements in tunnel mode policies is resolved.

Check that there are currently no security associations

setkey -D setkey -PD

Add /etc/sysconfig/iptables rules permitting ESP, HA, IKE

# Under the *filter table section: # If you know all your peers you may want to restrict the following to accepting # only those IPsec peer addresses and on their associated inbound interfaces. # Allow ipsec esp, ah -A INPUT -p 50 -j ACCEPT -A INPUT -p 51 -j ACCEPT # # Allow ike (isakmp) initiated by others. # ike responses permitted by '--state ESTABLISHED -j ACCEPT' above. -A INPUT -p udp -m udp --sport 500 --dport 500 -j ACCEPT

Host-To-Host

Pre-shared key

Choose a pre-shared key and communicate it to the VPN peer administrator. Be careful not to let the key fall into other hands

Use a different pre-shared key for each organization.

Identify your public IP address and peer's public IP address

Configure /etc/sysconfig/network-scripts/ifcfg-ipsec0

ONBOOT=no TYPE=IPSEC IKE_METHOD=PSK SRC=my.pub.ip.addr DST=peer.pub.ip.addr

The SRC entry is not strictly required, but I like having it there for clarity, and because if I configure the peer as well, I just have to copy this file and switch the SRC/DST values.

Configure /etc/sysconfig/network-scripts/keys-ipsec0

IKE_PSK=yourPreSharedSecretMatchingAtBothEndpoints

Set keys-ipsec0 readable only by the owner (root)

chmod 600 /etc/sysconfig/network-scripts/keys-ipsec0

Start the ipsec0 'interface'

ifup ipsec0

Monitor communications with the peer while you make connections

In one terminal:

tcpdump host peer.pub.ip.addr <ctrl-c> to stop

In another terminal:

ping peer.pub.ip.addr

Check SAD and SPD

setkey -D setkey -PD

Stop the ipsec0 'interface'

ifdown ipsec0

Verify SPD no longer contains policy for partner endpoints configured by ipsec0

setkey -PD

Network-To-Network

The following examples presume the local private network is 172.16.0.0/12, and the peer's private network is 192.168.0.0/16.

Pre-shared-key

Choose a pre-shared key and communicate it to VPN peer administrator

Identify your public IP address and peer's public IP address.

Identify your network and peer's network.

Configure /etc/sysconfig/network-scripts/ifcfg-ipsec0

ONBOOT=no TYPE=IPSEC IKE_METHOD=PSK SRCNET=172.16.0.0/12 DSTNET=192.168.0.0/16 SRC=my.pub.ip.addr DST=peer.pub.ip.addr

Configure /etc/sysconfig/network-scripts/keys-ipsec0

IKE_PSK=yourPreSharedSecretMatchingAtBothEndpoints

Set keys-ipsec0 readable only by the owner (root)

chmod 600 /etc/sysconfig/network-scripts/keys-ipsec0

Start the ipsec0 'interface'

ifup ipsec0

Monitor communications with the peer while you make connections

In one terminal:

tcpdump host peer.pub.ip.addr <ctrl-c> to stop

Then use a host on one src or dest network to connect to a host on the other network.

Check SAD and SPD

setkey -D setkey -PD

Stop the ipsec0 'interface'

ifdown ipsec0

Verify SPD no longer contains policy for partner endpoints configured by ipsec0

setkey -PD

Firewalling Network-To-Network IPsec VPN Packets

Samples of how to control packets that come through an IPsec tunnel. Any IPsec ESP packets from a.b.c.d are marked with a "1" in the mangle table. Those from e.f.g.h are marked with a “2”. Use different mark values for different peers.

# Under the *mangle table section: # Mark packets that come in through IPSEC tunnels -A PREROUTING -i eth1 -p 50 -s a.b.c.d/32 -j MARK --set-mark 1 -A PREROUTING -i eth1 -p 50 -s e.f.g.h/32 -j MARK --set-mark 2

Once decrypted packets keep their marks, and rules in the INPUT or FORWARD chains of the filter table use those marks to send them through additional chains.

NOTE: Transport mode's packets never hit the *filter table unencrypted so this only works for tunnel mode packets.

In the following *filter table examples vpn 1 packets to x.x.x.x:80 are accepted, but other packets return from the check_vpn_1 chain and are subjected to the same rules as non-tunneled packets. vpn 2 packets to y.y.y.y:5900 are accepted, but other packets are explicitly rejected.

# Under the *filter table section: # ------- 'check_vpn_1' chain ------- -N check_vpn_1 -A check_vpn_1 -m state --state NEW -p tcp -m tcp -d x.x.x.x/32 --dport 80 -j LOG --log-prefix IPTABLES_DIRIGO_VPN_OK: -A check_vpn_1 -m state --state NEW -p tcp -m tcp -d x.x.x.x/32 --dport 80 -j ACCEPT # ------- end of 'check_vpn_1' chain ------- # ------- 'check_vpn_2' chain ------- -N check_vpn_2 -A check_vpn_2 -m state --state NEW -p tcp -m tcp -d y.y.y.y/32 --dport 5900 -j LOG --log-prefix IPTABLES_DNINJ_VPN_OK: -A check_vpn_2 -m state --state NEW -p tcp -m tcp -d y.y.y.y/32 --dport 5900 -j ACCEPT -A check_vpn_2 -j REJECT # ------- end of 'check_vpn_2' chain ------- # Still under the *filter table section: # What we check and allow coming through ipsec # Destined for gateway's private address... -A INPUT -m mark --mark 1 -j check_vpn_1 -A INPUT -m mark --mark 2 -j check_vpn_2 # Destined for other hosts on the private network... -A FORWARD -m mark --mark 1 -j check_vpn_1 -A FORWARD -m mark --mark 2 -j check_vpn_2

Sample syslog output from VPN 1 based connection:

Mar 7 21:05:41 chris kernel: IPTABLES_DIRIGO_VPN_OK:IN=eth1 OUT= MAC=00:05:5d:f1:cb:ae:00:08:54:d0:9d:3d:08:00 SRC=192.168.0.254 DST=172.16.0.1 LEN=60 TOS=0x10 PREC=0x00 TTL=64 ID=62334 DF PROTO=TCP SPT=32818 DPT=80 WINDOW=5840 RES=0x00 CWR ECE SYN URGP=0

Notice that once decrypted, as far as filter table rules are concerned IN=eth1, thus the interface the ESP packet came in is the apparent input interface of the tunneled packet, and the source and destination addresses and ports are the same as if it were never encrypted.

Only the mark persisting from ESP packet allows us to distinguish real tunneled packets.

Network-To-Network

X509 Certificates

You need to create an X509 certificate on both peers, and exchange the public certificates while keeping the private keys on which they are based secure.

Create a 'certificate request':

openssl req -new -nodes -newkey rsa:1024 -sha1 -keyform PEM -keyout mykey.private -outform PEM -out request.pem

Then answer questions about the identity for the certificate...

Don't bother setting a challenge password for the request

Self sign the request:

openssl x509 -req -in request.pem -signkey mykey.private -out mykey.public

Delete request.pem since it is no longer needed:

rm request.pem

Distribute the .public certificate file to peer(s), but keep the .private key secret!

Put your private and public keys and your peer's public key in /etc/racoon/certs/

You can delete /etc/sysconfig/network-scripts/keys-ipsec0 if it exists, because it is not needed.

Reconfigure /etc/sysconfig/network-scripts/ifcfg-ipsec0 (presuming the local private network is 172.16.0.0/12, and the peer's private network is 192.168.0.0/16)

ONBOOT=no TYPE=IPSEC IKE_METHOD=X509 IKE_CERTFILE=mykey IKE_PEER_CERTFILE=peerkey SRCNET=172.16.0.0/12 DSTNET=192.168.0.0/16 SRC=my.pub.ip.addr DST=peer.pub.ip.addr

That's it. You are ready to start the new interface and test, just as in the pre-shared key example.

2004-07-24T20:07:34