Dirtbag's Blog

LibreVPN between two linux boxes

[ link: librevpn | tags: vpn linux ipsec | updated: Fri, 17 Apr 2020 12:09:26 -0400 ]

I have seen a lot of howtos for doing a lan to lan VPN on linux with openswan/freeswan/libreswan/etc, on the innernets. But when it came time for me to implement one for myself, It seems like there was a lot of misinformation and missing information in a lot of these howtos. I will document here a proceedure that will hopefully be of real use to someone else out there.

So I wanted to set up a Lan-to-Lan vpn using ipsec between two linux boxes that hosts "behind" the linux hosts could reach as if they were on the same network. One of my linux servers is a VM and the other is a raspberry pi running raspbian linux. The VM is running CentOS release 6.5. I just did a yum -y install libreswan and ended up with libreswan-3.7-1.el6.x86_64. For the Raspberry Pi, there was a version of openswan or strongswan available, but I wanted both sides to run the libreswan. So I downloaded and installed libreswan-3.8. NOTE: out of the box, libreswan will fail miserably when you try to compile it on the ARM architecture. You will get a bunch of errors as follows:

 cc1: error: bad value (generic) for -mtune switch

To fix this, edit the Makefile.inc and around line 244 there is a line that shows:

USERCOMPILE?=-g -O2 ${GCCM} ${WERROR} $(GCC_LINT) -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-all --param=ssp-buffer-size=4  -mtune=generic -fno-strict-aliasing -fPIE -DPIE  

Remove the -mtune=generic so that it looks like

USERCOMPILE?=-g -O2 ${GCCM} ${WERROR} $(GCC_LINT) -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-all --param=ssp-buffer-size=4 -fno-strict-aliasing -fPIE -DPIE  

After you have Libreswan installed on both sides, we will need to configure them both. There is only two files on each side that need to be edited.
/etc/ipsec.conf and /etc/ipsec.secrets

My network topology is as follows (raspberry pi(10.1.1.0/24) on the left and the centos vm(10.9.1.0/24) on the right):
10.1.1.0/24------------raspberry pi---------====innernets====---------centos vm------------10.9.1.0/24
Note: both the raspberry pi and the centos VM are doing masquerading for their respective networks in order for hosts behind them to get out to the internet.

So the ipsec.conf for both sides look like this:

 config setup
    protostack=netkey

conn ipsec
    type=tunnel
    authby=secret
    left=xxx.xxx.170.173
        leftsubnet= 10.1.1.0/24
        right=yyy.yyy.134.31
        rightsubnet=10.9.1.0/24
        esp= 3des-md5-96
        keyexchange= ike
        pfs= no
        auto= start

The left and right options above represent the valid ip addresses assigned to the centos vm and the raspberry pi and have been obfuscated. You would obviously need to substitute values for your networks accordingly.

The other file to edit is the /etc/ipsec.secrets file which has the ipsec "pre-shared" key which is the password that both sides use to negotiate the tunnel.
On the raspberry pi side, the file looks like:

 xxx.xxx.170.173 yyy.yyy.134.31 : PSK "mysecretsquirrelpassword"

On the centos vm side, the /etc/ipsec.secrets file will look like this:

 yyy.yyy.134.31 xxx.xxx.170.173:  PSK "mysecretsquirrelpassword"


again, I have obfuscated the valid ip addresses assigned to my hosts.. But these are the valid ip addresses from your isp that the linux servers would be using to communicate to the internet. Also, the value for PSK on both sides must match.


A few more things we must do for this tunnel to actually work.


1. Start up the librevpn daemons on both sides. Ususally with service ipsec start. You should also enable the service to start at boot time.

2. We must enable ip forwarding on both linux servers.
     There is enough info on how to do this already, just go google it. ッ Hint: net.ipv4.ip_forward

3. We must fix the iptables rules so that the two local networks will not get NAT'd when they try to communicate with each other.
     You can do the following on the centos vm side:

 /sbin/iptables -t nat -I POSTROUTING -s 10.9.1.0/24 -d 10.1.1.0/24 -j RETURN

and the following on the raspberry pi side

 /sbin/iptables -t nat -I POSTROUTING -s 10.1.1.0/24 -d 10.9.1.0/24 -j RETURN


4. We must adjust the iptables firewall to allow the ipsec communications. This would be on both sides.

/sbin/iptables -A INPUT -p ESP --in-interface eth1 --j ACCEPT
/sbin/iptables -A INPUT -p UDP --source-port 500 --destination-port 500 --in-interface eth1 --j ACCEPT


Note: This is assuming that eth1 is the "outside" interface with the valid ip address on it.

Now all thats needed is to start the ipsec service on both sides and try to initiate some traffic from one side to the other.

The tricky part is that you will not see any tunnel interfaces or routes added for the remote networks. Some output you can look at to see if
your tunnel is working or not is from the output of ipsec auto --status or ip xfrm policy

jason@raspberrypi ~ $ sudo ip xfrm policy
src 10.1.1.0/24 dst 10.9.1.0/24 
    dir out priority 2344 
    tmpl src xxx.xxx.170.173 dst yyy.yyy.134.31
        proto esp reqid 16385 mode tunnel
src 10.9.1.0/24 dst 10.1.1.0/24 
    dir fwd priority 2344 
    tmpl src yyy.yyy.134.31 dst xxx.xxx.170.173
        proto esp reqid 16385 mode tunnel
src 10.9.1.0/24 dst 10.1.1.0/24 
    dir in priority 2344 
    tmpl src yyy.yyy.134.31 dst xxx.xxx.170.173
        proto esp reqid 16385 mode tunnel
src ::/0 dst ::/0 
    socket out priority 0 
src ::/0 dst ::/0 
    socket in priority 0 
src 0.0.0.0/0 dst 0.0.0.0/0 
    socket out priority 0 
src 0.0.0.0/0 dst 0.0.0.0/0 
    socket in priority 0 
src 0.0.0.0/0 dst 0.0.0.0/0 
    socket out priority 0 
src 0.0.0.0/0 dst 0.0.0.0/0 
    socket in priority 0 
src 0.0.0.0/0 dst 0.0.0.0/0 
    socket out priority 0 
src 0.0.0.0/0 dst 0.0.0.0/0 
    socket in priority 0 
jason@raspberrypi ~ $ 




jason@raspberrypi ~ $ sudo ipsec auto --status
000 using kernel interface: netkey
000 interface lo/lo ::1
000 interface lo/lo 127.0.0.1
000 interface eth0/eth0 10.1.1.1
000 interface eth1/eth1 xxx.xxx.170.173
000  
000 fips mode=disabled;
000 SElinux=disabled
000  
000 config setup options:
000  
000 configdir=/etc, configfile=/etc/ipsec.conf, secrets=/etc/ipsec.secrets, ipsecdir=/etc/ipsec.d, dumpdir=/var/run/pluto, statsbin=unset
000 sbindir=/usr/local/sbin, libdir=/usr/local/libexec/ipsec, libexecdir=/usr/local/libexec/ipsec
000 pluto_version=3.8, pluto_vendorid=OE-Libreswan-3.8
000 nhelpers=-1, uniqueids=yes, retransmits=yes, force_busy=no
000 ikeport=500, strictcrlpolicy=no, crlcheckinterval=0, listen=
000 secctx_attr_value=
000 myid = (none)
000 debug none
000  
000 nat_traversal=no, keep_alive=20, nat_ikeport=4500, disable_port_floating=yes
000  
000 ESP algorithms supported:
000  
000 algorithm ESP encrypt: id=2, name=ESP_DES, ivlen=8, keysizemin=64, keysizemax=64
000 algorithm ESP encrypt: id=3, name=ESP_3DES, ivlen=8, keysizemin=192, keysizemax=192
000 algorithm ESP encrypt: id=6, name=ESP_CAST, ivlen=8, keysizemin=40, keysizemax=128
000 algorithm ESP encrypt: id=11, name=ESP_NULL, ivlen=0, keysizemin=0, keysizemax=0
000 algorithm ESP encrypt: id=12, name=ESP_AES, ivlen=8, keysizemin=128, keysizemax=256
000 algorithm ESP encrypt: id=14, name=ESP_AES_CCM_A, ivlen=8, keysizemin=128, keysizemax=256
000 algorithm ESP encrypt: id=15, name=ESP_AES_CCM_B, ivlen=8, keysizemin=128, keysizemax=256
000 algorithm ESP encrypt: id=16, name=ESP_AES_CCM_C, ivlen=8, keysizemin=128, keysizemax=256
000 algorithm ESP encrypt: id=18, name=ESP_AES_GCM_A, ivlen=8, keysizemin=128, keysizemax=256
000 algorithm ESP encrypt: id=19, name=ESP_AES_GCM_B, ivlen=12, keysizemin=128, keysizemax=256
000 algorithm ESP encrypt: id=20, name=ESP_AES_GCM_C, ivlen=16, keysizemin=128, keysizemax=256
000 algorithm ESP auth attr: id=1, name=AUTH_ALGORITHM_HMAC_MD5, keysizemin=128, keysizemax=128
000 algorithm ESP auth attr: id=2, name=AUTH_ALGORITHM_HMAC_SHA1, keysizemin=160, keysizemax=160
000 algorithm ESP auth attr: id=5, name=AUTH_ALGORITHM_HMAC_SHA2_256, keysizemin=256, keysizemax=256
000 algorithm ESP auth attr: id=6, name=AUTH_ALGORITHM_HMAC_SHA2_384, keysizemin=384, keysizemax=384
000 algorithm ESP auth attr: id=7, name=AUTH_ALGORITHM_HMAC_SHA2_512, keysizemin=512, keysizemax=512
000 algorithm ESP auth attr: id=9, name=AUTH_ALGORITHM_AES_CBC, keysizemin=128, keysizemax=128
000 algorithm ESP auth attr: id=251, name=AUTH_ALGORITHM_NULL_KAME, keysizemin=0, keysizemax=0
000  
000 IKE algorithms supported:
000  
000 algorithm IKE encrypt: v1id=0, v1name=0??, v2id=20, v2name=AES_GCM_C, blocksize=16, keydeflen=128
000 algorithm IKE encrypt: v1id=0, v1name=0??, v2id=19, v2name=AES_GCM_B, blocksize=16, keydeflen=128
000 algorithm IKE encrypt: v1id=0, v1name=0??, v2id=18, v2name=AES_GCM_A, blocksize=16, keydeflen=128
000 algorithm IKE encrypt: v1id=0, v1name=0??, v2id=16, v2name=AES_CCM_C, blocksize=16, keydeflen=128
000 algorithm IKE encrypt: v1id=0, v1name=0??, v2id=15, v2name=AES_CCM_B, blocksize=16, keydeflen=128
000 algorithm IKE encrypt: v1id=0, v1name=0??, v2id=14, v2name=AES_CCM_A, blocksize=16, keydeflen=128
000 algorithm IKE encrypt: v1id=5, v1name=OAKLEY_3DES_CBC, v2id=3, v2name=3DES, blocksize=8, keydeflen=192
000 algorithm IKE encrypt: v1id=7, v1name=OAKLEY_AES_CBC, v2id=12, v2name=AES_CBC, blocksize=16, keydeflen=128
000 algorithm IKE encrypt: v1id=65004, v1name=OAKLEY_SERPENT_CBC, v2id=65004, v2name=SERPENT_CBC, blocksize=16, keydeflen=128
000 algorithm IKE encrypt: v1id=65005, v1name=OAKLEY_TWOFISH_CBC, v2id=65005, v2name=TWOFISH_CBC, blocksize=16, keydeflen=128
000 algorithm IKE encrypt: v1id=65289, v1name=OAKLEY_TWOFISH_CBC_SSH, v2id=65289, v2name=TWOFISH_CBC_SSH, blocksize=16, keydeflen=128
000 algorithm IKE hash: id=1, name=OAKLEY_MD5, hashsize=16
000 algorithm IKE hash: id=2, name=OAKLEY_SHA1, hashsize=20
000 algorithm IKE hash: id=4, name=OAKLEY_SHA2_256, hashsize=32
000 algorithm IKE hash: id=5, name=OAKLEY_SHA2_384, hashsize=48
000 algorithm IKE hash: id=6, name=OAKLEY_SHA2_512, hashsize=64
000 algorithm IKE dh group: id=2, name=OAKLEY_GROUP_MODP1024, bits=1024
000 algorithm IKE dh group: id=5, name=OAKLEY_GROUP_MODP1536, bits=1536
000 algorithm IKE dh group: id=14, name=OAKLEY_GROUP_MODP2048, bits=2048
000 algorithm IKE dh group: id=15, name=OAKLEY_GROUP_MODP3072, bits=3072
000 algorithm IKE dh group: id=16, name=OAKLEY_GROUP_MODP4096, bits=4096
000 algorithm IKE dh group: id=17, name=OAKLEY_GROUP_MODP6144, bits=6144
000 algorithm IKE dh group: id=18, name=OAKLEY_GROUP_MODP8192, bits=8192
000 algorithm IKE dh group: id=22, name=OAKLEY_GROUP_DH22, bits=1024
000 algorithm IKE dh group: id=23, name=OAKLEY_GROUP_DH23, bits=2048
000 algorithm IKE dh group: id=24, name=OAKLEY_GROUP_DH24, bits=2048
000  
000 stats db_ops: {curr_cnt, total_cnt, maxsz} :context={0,7,36} trans={0,7,924} attrs={0,7,1232} 
000  
000 Connection list:
000  
000 "nibbler": 10.1.1.0/24===xxx.xxx.170.173...yyy.yyy.134.31===10.9.1.0/24; erouted; eroute owner: #59
000 "nibbler":     oriented; my_ip=unset; their_ip=unset;
000 "nibbler":   xauth info: us:none, them:none,  my_xauthuser=[any]; their_xauthuser=[any]; ;
000 "nibbler":   modecfg info: us:none, them:none, modecfg policy:push, dns1:unset, dns2:unset, domain:unset, banner:unset;
000 "nibbler":   labeled_ipsec:no, loopback:no; 
000 "nibbler":    policy_label:unset; 
000 "nibbler":   ike_life: 3600s; ipsec_life: 28800s; rekey_margin: 540s; rekey_fuzz: 100%; keyingtries: 0;
000 "nibbler":   sha2_truncbug:no; initial_contact:no; cisco_unity:no; send_vendorid:no;
000 "nibbler":   policy: PSK+ENCRYPT+TUNNEL+UP+IKEv2ALLOW+SAREFTRACK+IKE_FRAG; 
000 "nibbler":   conn_prio: 24,24; interface: eth1; metric: 0; mtu: unset; sa_prio:auto;
000 "nibbler":   newest ISAKMP SA: #68; newest IPsec SA: #59; 
000 "nibbler":   IKE algorithm newest: AES_CBC_128-SHA1-MODP2048
000 "nibbler":   ESP algorithms wanted: 3DES(3)_000-MD5(1)_096
000 "nibbler":   ESP algorithms loaded: 3DES(3)_192-MD5(1)_096
000 "nibbler":   ESP algorithm newest: 3DES_000-HMAC_MD5; pfsgroup=
000  
000 Total IPsec connections: loaded 1, active 1
000  
000 State list:
000  
000 #59: "nibbler":500 STATE_QUICK_I2 (sent QI2, IPsec SA established); EVENT_SA_REPLACE in 1955s; newest IPSEC; eroute owner; isakmp#58; idle; import:admin initiate
000 #59: "nibbler" esp.5786fcda@yyy.yyy.134.31 esp.b6e6a1e6@xxx.xxx.170.173 tun.0@yyy.yyy.134.31 tun.0@xxx.xxx.170.173 ref=0 refhim=4294901761 Traffic: ESPin=9KB ESPout=190KB! ESPmax=4194303B 
000 #68: "nibbler":500 STATE_MAIN_I4 (ISAKMP SA established); EVENT_SA_REPLACE in 494s; newest ISAKMP; lastdpd=-1s(seq in:0 out:0); idle; import:admin initiate
000  
000 Shunt list:
000  

-db

Like this article? Buy me a beer!