Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
BashScript for connecting VPN between VPC G/W and Debian Linux. operating HA by monit.
#!/bin/bash
#
# Setup VPN between Debian Linux and VPC G/W.
# How to use : ./this_script.sh Generic.txt
#
# For connecting IPsec VPN, you need to allow these connections.
# If VPN has global address, you change FORWARD to OUTPUT.
#
# ex) iptables -A FORWARD -p udp --dport 500 -j ACCEPT
# iptables -A FORWARD -p tcp --dport 500 -j ACCEPT
# iptables -A FORWARD -p esp -j ACCEPT
#
PATH=/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
exitMessage() {
echo "$@" >&2
exit 1
}
[ `id -u` = 0 ] || exitMessage "Set user to root."
#
# Opetion
#
CONF=$1
[ -z "$CONF" -o ! -r "$CONF" ] && exitMessage "Input VPC+VPN Generic config."
#########
#
# Config
#
HOSTNAME=`hostname`
INTERFACE="eth0"
CUSTOMER_SOURCE="172.30.4.0/22"
VPC_SUBNET="10.100.0.0/16"
QUAGGA_PASSWORD="QuaggaPassword"
CUSTOMER_SUBNET=`LANG=C ip addr show dev $INTERFACE \
| grep -m1 "inet " | sed -e 's/^.*inet \([\.0-9\/]\+\) .*/\1/g'`
CUSTOMER_ADDR=`echo "$CUSTOMER_SUBNET" | cut -d/ -f1`
RACOON_LOG="/var/log/racoon/racoon.log"
BGPD_LOG="/var/log/quagga/bgpd.log"
DEPLOY_DIR="/usr/local/etc/aws-vpc/"
VPN1_DIR=$DEPLOY_DIR"vpn1/"
VPN2_DIR=$DEPLOY_DIR"vpn2/"
EMAIL="root@localhost"
#########
#
# Generic Config Values
#
CONNECTION_ID=`cat $CONF | grep "Your VPN Connection ID" | awk '{print $6}'`
T1_OUT_CUSTOMER_GW=`cat $CONF | grep -m1 "\- Customer Gateway" | tail -1 | awk '{print $5}'`
T1_OUT_VPC_GW=` cat $CONF | grep -m1 "\- Virtual Private Gateway" | tail -1 | awk '{print $6}'`
T1_IN_CUSTOMER_GW=` cat $CONF | grep -m2 "\- Customer Gateway" | tail -1 | awk '{print $5}'`
T1_IN_VPC_GW=` cat $CONF | grep -m2 "\- Virtual Private Gateway" | tail -1 | awk '{print $6}'`
T1_PSK=` cat $CONF | grep -m1 "\- Pre-Shared Key" | tail -1 | awk '{print $5}'`
T1_ASN=` cat $CONF | grep -m1 "Private *Gateway ASN" | tail -1 | awk '{print $7}'`
T1_NEIGHBOR_ADDR=` cat $CONF | grep -m1 "Neighbor IP Address" | tail -1 | awk '{print $6}'`
T2_OUT_CUSTOMER_GW=`cat $CONF | grep -m4 "\- Customer Gateway" | tail -1 | awk '{print $5}'`
T2_OUT_VPC_GW=` cat $CONF | grep -m3 "\- Virtual Private Gateway" | tail -1 | awk '{print $6}'`
T2_IN_CUSTOMER_GW=` cat $CONF | grep -m5 "\- Customer Gateway" | tail -1 | awk '{print $5}'`
T2_IN_VPC_GW=` cat $CONF | grep -m4 "\- Virtual Private Gateway" | tail -1 | awk '{print $6}'`
T2_PSK=` cat $CONF | grep -m2 "\- Pre-Shared Key" | tail -1 | awk '{print $5}'`
T2_ASN=` cat $CONF | grep -m2 "Private *Gateway ASN" | tail -1 | awk '{print $7}'`
T2_NEIGHBOR_ADDR=` cat $CONF | grep -m2 "Neighbor IP Address" | tail -1 | awk '{print $6}'`
VALUES="T1_OUT_CUSTOMER_GW T1_OUT_VPC_GW T1_IN_CUSTOMER_GW T1_IN_VPC_GW"
VALUES+=" T1_PSK T1_ASN T1_NEIGHBOR_ADDR"
VALUES+=" T2_OUT_CUSTOMER_GW T2_OUT_VPC_GW T2_IN_CUSTOMER_GW T2_IN_VPC_GW"
VALUES+=" T2_PSK T2_ASN T2_NEIGHBOR_ADDR"
for v in $VALUES
do
[ -z `eval 'echo $'$v` ] && exitMessage "Colud not found $v from $CONF."
done
T1_IN_VPC_ADDR=`echo "$T1_IN_VPC_GW" | cut -d/ -f1`
T2_IN_VPC_ADDR=`echo "$T2_IN_VPC_GW" | cut -d/ -f1`
#########
#
# Package
#
apt-get -y install racoon ipsec-tools quagga monit
#########
#
# sysctl
#
cat << EOT > /etc/sysctl.d/vpn.conf
net.ipv4.ip_forward = 1
# prevent the panic of client, when switching vpn route.
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.eth0.send_redirects = 0
net.ipv4.conf.lo.send_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.eth0.accept_redirects = 0
net.ipv4.conf.lo.accept_redirects = 0
EOT
service procps restart
#########
#
# Create Config File
#
mkdir -p $VPN1_DIR $VPN2_DIR
## Pre-Shared Key ##
cat << EOT > /etc/racoon/aws-vpc.txt
$T1_OUT_VPC_GW $T1_PSK
$T2_OUT_VPC_GW $T2_PSK
EOT
chmod 600 /etc/racoon/aws-vpc.txt
#
# Racoon
#
cat << EOT > $VPN1_DIR/racoon.conf
log notify;
path pre_shared_key "/etc/racoon/aws-vpc.txt";
remote $T1_OUT_VPC_GW {
exchange_mode main;
lifetime time 28800 seconds;
proposal {
encryption_algorithm aes128;
hash_algorithm sha1;
authentication_method pre_shared_key;
dh_group 2;
}
}
sainfo address $T1_IN_CUSTOMER_GW any address $T1_IN_VPC_GW any {
pfs_group 2;
lifetime time 3600 seconds;
encryption_algorithm aes128;
authentication_algorithm hmac_sha1;
compression_algorithm deflate;
}
EOT
cat << EOT > $VPN2_DIR/racoon.conf
log notify;
path pre_shared_key "/etc/racoon/aws-vpc.txt";
remote $T2_OUT_VPC_GW {
exchange_mode main;
lifetime time 28800 seconds;
proposal {
encryption_algorithm aes128;
hash_algorithm sha1;
authentication_method pre_shared_key;
dh_group 2;
}
}
sainfo address $T2_IN_CUSTOMER_GW any address $T2_IN_VPC_GW any {
pfs_group 2;
lifetime time 3600 seconds;
encryption_algorithm aes128;
authentication_algorithm hmac_sha1;
compression_algorithm deflate;
}
EOT
#
# Setkey
#
cat << EOT > /etc/ipsec-tools.d/10-vpc-tunnels.conf
#!/usr/sbin/setkey -f
flush;
spdflush;
# Tunnel1
spdadd $T1_IN_CUSTOMER_GW $T1_IN_VPC_GW any -P out ipsec esp/tunnel/$CUSTOMER_ADDR-$T1_OUT_VPC_GW/require;
spdadd $T1_IN_VPC_GW $T1_IN_CUSTOMER_GW any -P in ipsec esp/tunnel/$T1_OUT_VPC_GW-$CUSTOMER_ADDR/require;
spdadd $T1_IN_CUSTOMER_GW $VPC_SUBNET any -P out ipsec esp/tunnel/$CUSTOMER_ADDR-$T1_OUT_VPC_GW/require;
spdadd $VPC_SUBNET $T1_IN_CUSTOMER_GW any -P in ipsec esp/tunnel/$T1_OUT_VPC_GW-$CUSTOMER_ADDR/require;
# Tunnel2
spdadd $T2_IN_CUSTOMER_GW $T2_IN_VPC_GW any -P out ipsec esp/tunnel/$CUSTOMER_ADDR-$T2_OUT_VPC_GW/require;
spdadd $T2_IN_VPC_GW $T2_IN_CUSTOMER_GW any -P in ipsec esp/tunnel/$T2_OUT_VPC_GW-$CUSTOMER_ADDR/require;
spdadd $T2_IN_CUSTOMER_GW $VPC_SUBNET any -P out ipsec esp/tunnel/$CUSTOMER_ADDR-$T2_OUT_VPC_GW/require;
spdadd $VPC_SUBNET $T2_IN_CUSTOMER_GW any -P in ipsec esp/tunnel/$T2_OUT_VPC_GW-$CUSTOMER_ADDR/require;
EOT
cat << EOT > $VPN1_DIR/20-vpc-private.conf
#!/usr/sbin/setkey -f
# VPN1 Between Local and VPC
spdadd $CUSTOMER_SOURCE $VPC_SUBNET any -P out ipsec esp/tunnel/$CUSTOMER_ADDR-$T1_OUT_VPC_GW/require;
spdadd $VPC_SUBNET $CUSTOMER_SOURCE any -P in ipsec esp/tunnel/$T1_OUT_VPC_GW-$CUSTOMER_ADDR/require;
EOT
cat << EOT > $VPN2_DIR/20-vpc-private.conf
#!/usr/sbin/setkey -f
# VPN2 Between Local and VPC
spdadd $CUSTOMER_SOURCE $VPC_SUBNET any -P out ipsec esp/tunnel/$CUSTOMER_ADDR-$T2_OUT_VPC_GW/require;
spdadd $VPC_SUBNET $CUSTOMER_SOURCE any -P in ipsec esp/tunnel/$T2_OUT_VPC_GW-$CUSTOMER_ADDR/require;
EOT
#
# bgpd
#
cat << EOT > $VPN1_DIR/bgpd.conf
hostname $HOSTNAME
password $QUAGGA_PASSWORD
enable password $QUAGGA_PASSWORD
!
log file $BGPD_LOG
!debug bgp events
!debug bgp zebra
debug bgp updates
!
router bgp 65000
bgp router-id $CUSTOMER_ADDR
network $T1_IN_CUSTOMER_GW
! Routing for VPC to CUSTOMER (see Route Tables on VPC Console)
! if CustomerVPN forward using NAT, this is unnecessary.
network $CUSTOMER_SUBNET
!
! aws tunnel #1 neighbor
neighbor $T1_NEIGHBOR_ADDR remote-as $T1_ASN
!
line vty
EOT
cat << EOT > $VPN2_DIR/bgpd.conf
hostname $HOSTNAME
password $QUAGGA_PASSWORD
enable password $QUAGGA_PASSWORD
!
log file $BGPD_LOG
!debug bgp events
!debug bgp zebra
debug bgp updates
!
router bgp 65000
bgp router-id $CUSTOMER_ADDR
network $T2_IN_CUSTOMER_GW
! Routing for VPC to CUSTOMER (see Route Tables on VPC Console)
! if CustomerVPN forward using NAT, this is unnecessary.
network $CUSTOMER_SUBNET
!
! aws tunnel #2 neighbor
neighbor $T2_NEIGHBOR_ADDR remote-as $T2_ASN
!
line vty
EOT
#
# zebra config
#
cat << EOT > /etc/quagga/zebra.conf
hostname $HOSTNAME
password $QUAGGA_PASSWORD
enable password $QUAGGA_PASSWORD
!
! list interfaces
interface $INTERFACE
interface lo
!
line vty
EOT
#
# Racoon log
#
sed -i "s|RACOON_ARGS.*$|RACOON_ARGS='-l $RACOON_LOG'|g" /etc/default/racoon
cat << EOT > /etc/logrotate.d/racoon
$RACOON_LOG {
rotate 10
daily
compress
missingok
notifempty
copytruncate
}
EOT
#
# Monit
#
MONIT_HEALTHCHECK_SCRIPT="/usr/local/bin/aws-vpc-healthcheck.sh"
MONIT_SWITCH_SCRIPT="/usr/local/bin/aws-vpc-switch.sh"
cat << EOT > /etc/monit/conf.d/aws-vpc.cfg
set daemon 10 with start delay 5
set mailserver localhost
set alert $EMAIL not on {INSTANCE}
check program aws-vpc
with path $MONIT_HEALTHCHECK_SCRIPT
if status != 0 for 10 cycles then exec "$MONIT_SWITCH_SCRIPT"
every 3 cycles
check process racoon with pidfile /var/run/racoon.pid
start program = "/etc/init.d/racoon start"
stop program = "/etc/init.d/racoon stop"
check process quagga with pidfile /var/run/quagga/zebra.pid
start program = "/etc/init.d/quagga start"
stop program = "/etc/init.d/quagga stop"
EOT
cat << EOT > $MONIT_HEALTHCHECK_SCRIPT
#!/bin/bash
#
# AWS VPC VPN healthcheck script.
#
# Error is that local can't ping to current vpc tunnel.
#
# Config
T1_OUT_VPC_GW=$T1_OUT_VPC_GW
T2_OUT_VPC_GW=$T2_OUT_VPC_GW
T1_IN_VPC_ADDR=$T1_IN_VPC_ADDR
T2_IN_VPC_ADDR=$T2_IN_VPC_ADDR
# Check setkey
OUT_VPN_NUMBER=0
SETKEY_ROUTE=\`/usr/sbin/setkey -D -P | grep -m1 -A5 "$CUSTOMER_SOURCE" | grep -m1 "esp/tunnel"\`
echo "\$SETKEY_ROUTE" | grep \$T1_OUT_VPC_GW > /dev/null 2>&1
[ \$? -eq 0 ] && OUT_VPN_NUMBER=1
echo "\$SETKEY_ROUTE" | grep \$T2_OUT_VPC_GW > /dev/null 2>&1
[ \$? -eq 0 ] && OUT_VPN_NUMBER=2
[ \$OUT_VPN_NUMBER -eq 0 ] && echo -n "Not set private route yet." >& 2 && exit 1
# Check ping
IN_VPC_ADDR=\`eval echo '\$T'\$OUT_VPN_NUMBER'_IN_VPC_ADDR'\`
ping -c 1 -w 1 \$IN_VPC_ADDR > /dev/null 2>&1
[ \$? -eq 0 ] && exit 0
# error
echo -n "VPN \$OUT_VPN_NUMBER tunnel is disconnected." >& 2
exit 1
EOT
chmod +x $MONIT_HEALTHCHECK_SCRIPT
cat << EOT > $MONIT_SWITCH_SCRIPT
#!/bin/bash
#
# Config
IPSEC_PRIVATE_CONF="/etc/ipsec-tools.d/20-vpc-private.conf"
VPN1_DIR="$VPN1_DIR"
VPN2_DIR="$VPN2_DIR"
CONF1=\$VPN1_DIR"20-vpc-private.conf"
CONF2=\$VPN2_DIR"20-vpc-private.conf"
# Check current conf
VPN_NUMBER=1
if [ -r "\$IPSEC_PRIVATE_CONF" ];then
diff \$IPSEC_PRIVATE_CONF \$CONF1 > /dev/null 2>&1
[ \$? -eq 0 ] && VPN_NUMBER=2
fi
# Overwrite
CONF_DIR=\`eval echo '\$VPN'\$VPN_NUMBER'_DIR'\`
cp \$CONF_DIR'racoon.conf' /etc/racoon/
cp \$CONF_DIR'20-vpc-private.conf' /etc/ipsec-tools.d/
cp \$CONF_DIR'bgpd.conf' /etc/quagga/
# Restart Services
service setkey restart
service racoon restart
service quagga restart
service monit restart
exit 0
EOT
chmod +x $MONIT_SWITCH_SCRIPT
#
# Enable zebra and bgpd
#
sed -i 's/zebra=no/zebra=yes/' /etc/quagga/daemons
sed -i 's/bgpd=no/bgpd=yes/' /etc/quagga/daemons
#
# Create Static Tunnel Addr
#
ip addr add $T1_IN_CUSTOMER_GW dev $INTERFACE
ip addr add $T2_IN_CUSTOMER_GW dev $INTERFACE
#
# Restart Services
#
$MONIT_SWITCH_SCRIPT
service setkey restart
service racoon restart
service quagga restart
service monit restart
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.