Skip to content

Instantly share code, notes, and snippets.

@hassenius
Created December 10, 2015 20:58
Show Gist options
  • Save hassenius/57c9e71784e6fa1af5fc to your computer and use it in GitHub Desktop.
Save hassenius/57c9e71784e6fa1af5fc to your computer and use it in GitHub Desktop.
OpenVPN Server to access private openstack networks network
heat_template_version: 2013-05-23
description: Create an OpenVPN server to create connectivity to private networks
parameters:
key_name:
type: string
label: Keypair Name
description: Name of a KeyPair to enable SSH access to the instance.
constraints:
- custom_constraint: nova.keypair
instance_type:
type: string
label: OpenVPN Instance Type
description: Instance type for the OpenVPN server.
constraints:
- custom_constraint: nova.flavor
image_id:
type: string
label: OpenVPN Image
description: Name or ID of the image to use for the OpenVPN server (Tested with ubuntu 14.04 LTS).
constraints:
- custom_constraint: glance.image
shared_net_id:
type: string
label: External Network
description: Name or ID of the shared network for which floating IP addresses will be allocated.
constraints:
- custom_constraint: neutron.network
private_net_id:
type: string
label: Private Network
description: Private network in which OpenVPN will be linked.
constraints:
- custom_constraint: neutron.network
vpn_cidr:
type: string
default: 10.9.0.0/24
description: OpenVPN CIDR. It has to be unique and must not overlap the CIDR of your private_net_id, shared_net_id, and neither of your clients connecting to the VPN.
allowed_downloads:
type: string
default: 1
description: How many times can the client access package be downloaded before the
resources:
# IP addresses
server_shared_ip:
type: OS::Neutron::FloatingIP
depends_on:
- server_private_ip
properties:
floating_network: { get_param: shared_net_id }
port_id: { get_resource: server_private_ip }
server_private_ip:
type: OS::Neutron::Port
properties:
network: { get_param: private_net_id }
security_groups: [{ get_resource: secgroup-ovpn },{ get_resource: secgroup-ssh }, { get_resource: secgroup-http-cred }]
# Security Groups
secgroup-ovpn:
type: OS::Neutron::SecurityGroup
properties:
description: Enable traffic external traffic on UDP:1194 for OpenVPN trafic
rules: [{protocol: udp, port_range_max: 1194, port_range_min: 1194},]
secgroup-ssh:
type: OS::Neutron::SecurityGroup
properties:
description: Enable traffic external traffic on SSH.
rules: [{protocol: tcp, port_range_max: 22, port_range_min: 22},]
secgroup-http-cred:
type: OS::Neutron::SecurityGroup
properties:
description: Enable http connection to download client credentials on port 8080 from internet
rules: [{protocol: tcp, port_range_max: 8080, port_range_min: 8080, remote_ip_prefix: 0.0.0.0/0},]
# Servers
openvpn_instance:
type: OS::Nova::Server
depends_on:
- server_private_ip
properties:
image: { get_param: image_id }
flavor: { get_param: instance_type }
key_name: { get_param: key_name }
networks:
- port: { get_resource: server_private_ip }
user_data_format: RAW
user_data:
get_resource: software-init
# Software
openvpn-packages:
type: OS::Heat::CloudConfig
properties:
cloud_config:
merge_how: 'dict(recurse_array,no_replace)+list(append)'
runcmd:
- ufw allow openvpn
packages:
- openvpn
- easy-rsa
- woof
- zip
openvpn-server-config:
type: OS::Heat::CloudConfig
depends_on:
- openvpn-packages
- server_shared_ip
properties:
cloud_config:
merge_how: 'dict(recurse_array,no_replace)+list(append)'
packages:
- ipcalc
write_files:
- path: /etc/openvpn/route-up.sh
owner: root:root
permissions: '0755'
content:
str_replace:
params:
"%vpncidr%": { get_param: vpn_cidr }
template: |
#!/bin/bash
/sbin/sysctl -n net.ipv4.conf.all.forwarding > /var/log/openvpn/net.ipv4.conf.all.forwarding.bak
/sbin/sysctl net.ipv4.conf.all.forwarding=1
/sbin/iptables-save > /var/log/openvpn/iptables.save
/sbin/iptables -t nat -F
/sbin/iptables -t nat -A POSTROUTING -s %vpncidr% -j MASQUERADE
- path: /etc/openvpn/down.sh
owner: root:root
permissions: '0755'
content: |
#!/bin/bash
FORWARDING=$(cat /var/log/openvpn/net.ipv4.conf.all.forwarding.bak)
echo "restoring net.ipv4.conf.all.forwarding=$FORWARDING"
/sbin/sysctl net.ipv4.conf.all.forwarding=$FORWARDING
/etc/openvpn/fw.stop
echo "Restoring iptables"
/sbin/iptables-restore < /var/log/openvpn/iptables.save
- path: /etc/openvpn/fw.stop
owner: root:root
permissions: '0755'
content: |
#!/bin/sh
echo "Stopping firewall and allowing everyone..."
/sbin/iptables -F
/sbin/iptables -X
/sbin/iptables -t nat -F
/sbin/iptables -t nat -X
/sbin/iptables -t mangle -F
/sbin/iptables -t mangle -X
/sbin/iptables -P INPUT ACCEPT
/sbin/iptables -P FORWARD ACCEPT
/sbin/iptables -P OUTPUT ACCEPT
- path: /etc/openvpn/server.conf
owner: root:root
permissions: '0644'
content: |
port 1194
proto udp
dev tun
ca /etc/openvpn/ca.crt
cert /etc/openvpn/server.crt
key /etc/openvpn/server.key
crl-verify /etc/openvpn/crl.pem
dh /etc/openvpn/dh2048.pem
server OVPN_IP OVPN_MASK
ifconfig-pool-persist ipp.txt
push "route PRIVATE_NETWORK_IP PRIVATE_NETWORK_MASK"
keepalive 10 120
tls-auth ta.key 0
comp-lzo
persist-key
persist-tun
status /var/log/openvpn/openvpn-status.log
log /var/log/openvpn/openvpn.log
verb 3
script-security 2
route-up /etc/openvpn/route-up.sh
down /etc/openvpn/down.sh
duplicate-cn
- path: /etc/openvpn/populate-configs.sh
owner: root:root
permissions: '0755'
content:
str_replace:
params:
"%public_ip%": { get_attr: [server_shared_ip, floating_ip_address] }
# { get_resource: floating }
"%vpncidr%": { get_param: vpn_cidr }
template: |
#!/bin/bash
echo "Populating OpenVPN Configs"
FLOATING_IP=%public_ip%
OVPN_IP=$(ipcalc -nb %vpncidr% | grep ^Address | awk '{print $2}')
OVPN_MASK=$(ipcalc -nb %vpncidr% | grep ^Netmask | awk '{print $2}')
PRIVATE_IP_CIDR=$(ip addr show dev eth0 | grep 'inet .*$' | awk '{print $2}')
PRIVATE_NETWORK_CIDR=$(ipcalc -nb $PRIVATE_IP_CIDR | grep ^Network | awk '{print $2}')
PRIVATE_NETWORK_IP=$(ipcalc -nb $PRIVATE_NETWORK_CIDR | grep ^Address | awk '{print $2}')
PRIVATE_NETWORK_MASK=$(ipcalc -nb $PRIVATE_NETWORK_CIDR | grep ^Netmask | awk '{print $2}')
cd /etc/openvpn
sed -i -e "s/PRIVATE_NETWORK_IP/$PRIVATE_NETWORK_IP/g" server.conf
sed -i -e "s/PRIVATE_NETWORK_MASK/$PRIVATE_NETWORK_MASK/g" server.conf
sed -i -e "s/OVPN_IP/$OVPN_IP/g" server.conf
sed -i -e "s/OVPN_MASK/$OVPN_MASK/g" server.conf
# Run some additional setup tasks
mkdir -p /var/log/openvpn
runcmd:
- /etc/openvpn/populate-configs.sh
# ufw interferes with iptables masquarading. Disable
- ufw disable
openvpn-server-certificate:
type: OS::Heat::SoftwareConfig
depends_on:
- openvpn-packages
- openvpn-server-config
properties:
config: |
#!/bin/bash
echo "Generating server certificates"
mkdir /etc/openvpn/easy-rsa
cp -r /usr/share/easy-rsa /etc/openvpn/
cd /etc/openvpn/easy-rsa
ln -s openssl-1.0.0.cnf openssl.cnf
source vars
./clean-all
./build-dh
KEY_EMAIL=ca@openvpn ./pkitool --initca
KEY_EMAIL=server@pilgrim ./pkitool --server server
KEY_EMAIL=revoked@pilgrim ./pkitool revoked
./revoke-full revoked # Generates a crl.pem revocation list
openvpn --genkey --secret keys/ta.key
ln keys/{ca.crt,server.crt,server.key,dh2048.pem,crl.pem,ta.key} /etc/openvpn/
echo "Starting OpenVPN"
# cloud-init entries might be out of order, with runcmd running after part-xxx are completed.
# spawn a while loop to wait for server.conf to be updated.
eval 'while grep -q OVPN_MASK /etc/openvpn/server.conf ; do echo "Waiting for configuration files to be updated...." ; sleep 2s ; done ; service openvpn start ' &
#while grep -q OVPN_MASK /etc/openvpn/server.conf ; do
# echo "Waiting for configuration files to be updated...."
# sleep 2s
#done
#service openvpn start
openvpn-client-certificate:
type: OS::Heat::SoftwareConfig
depends_on:
- openvpn-server-certificate
- server_shared_ip
properties:
config:
str_replace:
params:
"%public_ip%": { get_attr: [server_shared_ip, floating_ip_address] }
"%allowed_downloads%": { get_param: allowed_downloads }
template: |
#!/bin/bash
# Get the default user. This may change from system to system,
# but the cloud-init add user script has already run, so will be the
# last user in the system
user=$(tail -1 /etc/passwd | cut -d: -f1)
gid=$(tail -1 /etc/passwd | cut -d: -f3)
userhome=$(tail -1 /etc/passwd | cut -d: -f6)
echo "Creating the client OpenVPN config"
cat > /etc/openvpn/easy-rsa/client.conf <<EOF
client
dev tun
proto udp
# remote $FLOATING_IP 1194
remote %public_ip% 1194
resolv-retry infinite
nobind
user nobody
group nogroup
persist-key
persist-tun
ca keys/ca.crt
cert keys/client.crt
key keys/client.key
ns-cert-type server
tls-auth keys/ta.key 1
comp-lzo
verb 3
EOF
echo "Creating the client certificate"
cd /etc/openvpn/easy-rsa
source vars
KEY_EMAIL=client@pilgrim ./pkitool client
echo "Create and share vpnaccecss files"
zip vpnaccess.zip client.conf keys/ca.crt keys/client.key keys/client.crt keys/ta.key
mkdir -p ${userhome}/clientaccess
cp vpnaccess.zip ${userhome}/clientaccess
chown ${user}:${gid} ${userhome}/clientaccess/vpnaccess.zip
ufw allow 8080
ufw reload
cd ${userhome}/clientaccess
su -c 'woof -p 8080 -c %allowed_downloads% vpnaccess.zip ' ${user} >> /var/log/vpnclientdownloads.log 2>&1 &
software-init:
type: OS::Heat::MultipartMime
properties:
parts:
- config: { get_resource: openvpn-packages }
- config: { get_resource: openvpn-server-config }
- config: { get_resource: openvpn-server-certificate }
- config: { get_resource: openvpn-client-certificate }
## - config: { get_resource: share-client-cert }
outputs:
client_credentials:
description: You can download the OpenVPN client credentials from this link
value:
str_replace:
template: http://host:8080/vpnaccess.zip
params:
host: { get_attr: [server_shared_ip, floating_ip_address] }
private_network_ip:
description: Private network IP for the instance
value: { get_attr: [server_private_ip, fixed_ips, 0, ip_address] }
vpn_network:
description: Network address for the VPN network
value: { get_param: vpn_cidr }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment