cloud

How To Set A Server To Server VPN on Google Compute Engine

There are many cases where you wish to migrate data from one location to another. In most cases, you will wish to do it over a secure channel. In this tutorial we will see what are the main steps in order to set a VPN (in this case: StrongSwan) on Google Compute Engine so you will have a server to server VPN solution between your on own server(s) located in the basement and Compute Engine.
In this tutorial we will setup a VPN connection from your own datacenter to Compute Engine. First, let’s look at the big picture. We wish to have one gateway in our datacenter and another on Compute Engine. These gateways, will be responsible to connect and secure our channel so we could transfer our data over it in a secure way.

High Level Network diagram

VPN on GCE network macro view

Main steps

Pre-Setup Work

  • Set up a dedicated host at the client network.

  • Set up an external ip for the host and open port 4500 UDP

Compute Engine Work

1. Using the included management script, manageVPN.sh,  you will be able to set up the gateway host and all the required advanced networking.
Edit the following parameters before executing.

# Edit these to match your project and setup
PROJECT=Your-VPN-project-name-comes-here
NETWORK=main-gateway
GATEWAY_NAME=vpn-gateway
TEST_INSTANCE_NAME=client-1
TARGET_NETWORK="10.150.0.0/16"
MACHINE_TYPE=n1-standard-1
ZONE="us-central1-a"

2. Execute the setup script.

$ ./manageVPN.sh -p [your project] -n [your network] -i https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20131120 start

Please note that you can choose other Linux images.

3. Connect to the vpn gateway.

$ gcutil --project=your-project-name ssh vpn-gateway

4.  Create a file called ipsec.conf with the following contents:

config setup
# strictcrlpolicy=yes
# uniqueids = no
conn myconn
authby=psk
auto=start
dpdaction=restart
esp=aes128-sha1!
forceencaps=yes
ike=aes128-sha1-modp2048!
keyexchange=ikev2
mobike=no
type=tunnel
left=%any
leftfirewall=yes
leftsubnet=10.33.0.0/16
leftauth=psk
leftikeport=4500
right=108.59.85.118
rightsubnet=10.240.0.0/16
rightauth=psk
rightikeport=4500

5.   Execute the following on the host to install & configure strongSwan.
Use the ipsec.conf from above.

 On CentOS 6

sudo rpm -Uvh http://mirrors.kernel.org/fedora-epel/6/x86_64/epel-release-6-8.noarch.rpm
sudo yum install -y lsof man strongswan rng-tools
sudo sed -e 's/EXTRAOPTIONS=""/EXTRAOPTIONS="-r \/dev\/urandom"/' -i /etc/sysconfig/rngd
sudo ln -s /usr/sbin/strongswan /usr/sbin/ipsec
sudo service rngd start
sudo service ipsec start
sudo service strongswan start
sudo chkconfig rngd on
sudo chkconfig strongswan on
Enable IP forwarding on the gateway (you need to do both of the following):
1.Edit /etc/sysctl.conf and uncomment the line net.ipv4.ip_forward=1.
The next time the system reboots, it will load these settings.
2.For the current session, run sysctl -p to apply the changes to the running system.
6. Define a secret key for both sides.
Execute the following on the host to install & configure strongSwan.
Use the ipsec.conf from above.
echo "%any : PSK \"<secret-key>\"" | sudo tee /etc/strongswan/ipsec.secrets > /dev/null
sudo cp ipsec.conf /etc/strongswan
sudo ipsec restart
sudo ipsec up myconn
(to set MTU size for VPN encapsulation)
sudo ifconfig eth0 mtu 1300 up

Client Network Work

I recommend a dedicated (or low utilization) box to host the strongSwan VPN server. The following setup needs to be done on that host in addition to exposing the box to the internet on port 4500.

1. Create a file called ipsec.conf with the following contents:

config setup
conn myconn
authby=psk
auto=start
dpdaction=restart
esp=aes128-sha1!
forceencaps=yes
ike=aes128-sha1-modp2048!
keyexchange=ikev2
mobike=no
type=tunnel
left=%any
leftfirewall=yes
leftid=<< Edit with the external address of your local system >>
leftsubnet=<< Edit with your local network range >>
leftauth=psk
leftikeport=4500
right= << Add the external ip of the remote instance >>
rightsubnet=<< Edit with the remote network range >>
rightauth=psk
rightikeport=4500

2.   Execute the following on the host to install & configure strongSwan.

Use the ipsec.conf from above.

CentOS 6

sudo rpm -Uvh http://mirrors.kernel.org/fedora-epel/6/x86_64/epel-release-6-8.noarch.rpm <-- This might be changed... So check it on Fedora site
sudo yum install -y lsof man strongswan rng-tools
sudo vi /etc/sysconfig/rngd; EXTRAOPTIONS="-r /dev/urandom";
sudo ln -s /usr/sbin/strongswan /usr/sbin/ipsec
sudo service rngd start
sudo service ipsec start
sudo service strongswan start
sudo chkconfig rngd on
sudo chkconfig strongswan on
echo "%any : PSK \"<secret-key>\"" | sudo tee /etc/strongswan/ipsec.secrets > /dev/null
sudo cp ipsec.conf /etc/strongswan
# Enable IP forwarding on the gateway (you need to do both of the following):
1.Edit /etc/sysctl.conf and uncomment the line net.ipv4.ip_forward=1. The next time the system reboots, it will load these settings.
2.For the current session, run sysctl -p to apply the changes to the running system.

3. Update the secret key.  Execute the following on the host to install & configure strongSwan.  Use the ipsec.conf from above.

echo "%any : PSK \"<secret-key>\"" | sudo tee /etc/strongswan/ipsec.secrets > /dev/null
sudo cp ipsec.conf /etc/strongswan
sudo ipsec restart
sudo ipsec up myconn

4.  Set up routes on the cassandra hosts to reach the remote Compute Engine network via the local gateway host.

sudo route add -net 10.240.0.0/16 eth1
sudo route add -net 10.250.0.0/16 eth1
sudo ifconfig eth1 mtu 1300 up

Appendix

manageVPN.sh Script

#!/bin/sh
# Edit these to match your project and setup
PROJECT=vpn-lab
NETWORK=gce-network
GATEWAY_NAME=vpn-gateway-1
TEST_INSTANCE_NAME=povm-1
TARGET_NETWORK="10.150.0.0/16"
MACHINE_TYPE=n1-standard-1
ZONE="us-central1-a"
REGION="us-central1"
PRESHARED_KEY="googtest"
# End editable params
IPSEC_TEMPLATE="ipsec.template"
GCUTIL=`which gcutil`
IMAGE="https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120&quot;
while getopts ":p:n:i:t:" opt; do
case $opt in
p)
PROJECT=$OPTARG
;;
n)
NETWORK=$OPTARG
;;
i)
IMAGE=$OPTARG
;;
t)
TARGET_NETWORK=$OPTARG
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
🙂
echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
esac
done
PARAM=${@:$OPTIND:1}
if [ -z "$PARAM" ] ; then
echo $0 "[start | shutdown]"
fi
if [ "$PARAM" = "start" ] ; then
NETWORK_DETAILS=`$GCUTIL --project=$PROJECT listnetworks | grep $NETWORK`
SOURCE_NETWORK=`echo $NETWORK_DETAILS | awk -F'|' '{print $3}' | tr -d ' '`
SOURCE_GATEWAY=`echo $NETWORK_DETAILS | awk -F'|' '{print $4}' | tr -d ' '`
$GCUTIL --project=$PROJECT addinstance $GATEWAY_NAME --can_ip_forward=true \
--machine_type=$MACHINE_TYPE --persistent_boot_disk \
--network $NETWORK --external_ip ephemeral \
--zone $ZONE --image $IMAGE --tags vpn
GATEWAY_IP=`$GCUTIL --project=$PROJECT getinstance $GATEWAY_NAME | grep ' ip' | awk -F'|' '{print $3}' | tr -d ' '`
GATEWAY_EXTERNAL_IP=`gcutil --project=$PROJECT getinstance $GATEWAY_NAME | grep external-ip | awk -F'|' '{print $3}' | tr -d ' '`
# Reserve the external ip
$GCUTIL --project=$PROJECT reserveaddress --region=$REGION \
--source_address=$GATEWAY_EXTERNAL_IP gatewayip
# TODO: Set up the gateway software
# `/bin/cat install.template | sed -e 's/<secret_key>/$PRESHARED_KEY' > install.sh`
# $GCUTIL --project=$PROJECT put $GATEWAY_NAME install.sh .
# $GCUTIL --project=$PROJECT ssh $GATEWAY_NAME ./install.sh
$GCUTIL --project=$PROJECT addinstance $TEST_INSTANCE_NAME --network $NETWORK \
--image $IMAGE --zone us-central1-a \
--machine_type=$MACHINE_TYPE --persistent_boot_disk
$GCUTIL --project=$PROJECT addroute --network $NETWORK \
target-network-via-gateway $TARGET_NETWORK --next_hop_ip $GATEWAY_IP
$GCUTIL --project=$PROJECT addfirewall vpn-ssh --allowed_ip_sources 0.0.0.0/0 --allowed 'tcp:22' --network $NETWORK
$GCUTIL --project=$PROJECT addfirewall vpn-allow-internal --allowed_ip_sources 10.0.0.0/8 \
--allowed 'tcp:1-65535,udp:1-65535,icmp' \
--network $NETWORK --target_tags vpn
$GCUTIL --project=$PROJECT addfirewall vpn-allow-ipsec-nat --allowed_ip_sources $GATEWAY_EXTERNAL_IP/32 \
--allowed 'udp:4500' --network $NETWORK --target_tags vpn
$GCUTIL --project=$PROJECT addfirewall vpn-allow-all-peer --allowed_ip_sources $TARGET_NETWORK \
--allowed 'tcp:1-65535,udp:1-65535,icmp' --network $NETWORK --target_tags vpn
echo "EXTERNAL GATEWAY: $GATEWAY_EXTERNAL_IP"
elif [ "$PARAM" == "shutdown" ] ; then
$GCUTIL --project=$PROJECT deleteinstance -f --delete_boot_pd $GATEWAY_NAME
$GCUTIL --project=$PROJECT deleteinstance -f --delete_boot_pd $TEST_INSTANCE_NAME
$GCUTIL --project=$PROJECT deleteroute -f target-network-via-gateway
$GCUTIL --project=$PROJECT deletefirewall -f vpn-ssh
$GCUTIL --project=$PROJECT deletefirewall -f vpn-allow-internal
$GCUTIL --project=$PROJECT deletefirewall -f vpn-allow-ipsec-nat
$GCUTIL --project=$PROJECT deletefirewall -f vpn-allow-all-peer
$GCUTIL --project=$PROJECT releaseaddress --region=$REGION gatewayip --force
else
echo $0 "[start | shutdown ]"
fi

Misc

  1. The online documentation for Compute Engine.

  2. StrongSwan documentation.

Happy hacking.


Discover more from Ido Green

Subscribe to get the latest posts sent to your email.

Standard