mirror of https://github.com/apache/cloudstack.git
CLOUDSTACK-10013: Fix ipsec VPN configuration
- Fixes strongswan/ipsec, l2tpd and pppd configs - Uses auto=route in ipsec configs - Fixes road-warrior setup - Fixes site-to-site VPN with automatic connection configuration - Fixes vpc_vpn tests Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
parent
9aa7d4e818
commit
8c53574c91
|
|
@ -546,10 +546,6 @@ class CsSite2SiteVpn(CsDataBag):
|
|||
ikepolicy=obj['ike_policy'].replace(';','-')
|
||||
esppolicy=obj['esp_policy'].replace(';','-')
|
||||
|
||||
pfs='no'
|
||||
if 'modp' in esppolicy:
|
||||
pfs='yes'
|
||||
|
||||
if rightpeer in self.confips:
|
||||
self.confips.remove(rightpeer)
|
||||
file = CsFile(vpnconffile)
|
||||
|
|
@ -557,7 +553,6 @@ class CsSite2SiteVpn(CsDataBag):
|
|||
file.search("conn ", "conn vpn-%s" % rightpeer)
|
||||
file.addeq(" left=%s" % leftpeer)
|
||||
file.addeq(" leftsubnet=%s" % obj['local_guest_cidr'])
|
||||
file.addeq(" leftnexthop=%s" % obj['local_public_gateway'])
|
||||
file.addeq(" right=%s" % rightpeer)
|
||||
file.addeq(" rightsubnet=%s" % peerlist)
|
||||
file.addeq(" type=tunnel")
|
||||
|
|
@ -567,9 +562,8 @@ class CsSite2SiteVpn(CsDataBag):
|
|||
file.addeq(" ikelifetime=%s" % self.convert_sec_to_h(obj['ike_lifetime']))
|
||||
file.addeq(" esp=%s" % esppolicy)
|
||||
file.addeq(" lifetime=%s" % self.convert_sec_to_h(obj['esp_lifetime']))
|
||||
file.addeq(" pfs=%s" % pfs)
|
||||
file.addeq(" keyingtries=2")
|
||||
file.addeq(" auto=start")
|
||||
file.addeq(" auto=route")
|
||||
if 'encap' not in obj:
|
||||
obj['encap']=False
|
||||
file.addeq(" forceencaps=%s" % CsHelper.bool_to_yn(obj['encap']))
|
||||
|
|
@ -585,10 +579,20 @@ class CsSite2SiteVpn(CsDataBag):
|
|||
logging.info("Configured vpn %s %s", leftpeer, rightpeer)
|
||||
CsHelper.execute("ipsec rereadsecrets")
|
||||
|
||||
# This will load the new config and start the connection when needed since auto=start in the config
|
||||
# This will load the new config
|
||||
CsHelper.execute("ipsec reload")
|
||||
os.chmod(vpnsecretsfile, 0400)
|
||||
|
||||
for i in xrange(3):
|
||||
result = CsHelper.execute('ipsec status vpn-%s | grep "%s"' % (rightpeer, peerlist.split(",", 1)[0]))
|
||||
if len(result) > 0:
|
||||
break
|
||||
time.sleep(1)
|
||||
|
||||
# With 'auto=route', connections are established on an attempt to
|
||||
# communicate over the S2S VPN. This uses ping to initialize the connection.
|
||||
CsHelper.execute("timeout 5 ping -c 3 %s" % (peerlist.split("/", 1)[0].replace(".0", ".1")))
|
||||
|
||||
def convert_sec_to_h(self, val):
|
||||
hrs = int(val) / 3600
|
||||
return "%sh" % hrs
|
||||
|
|
@ -658,6 +662,7 @@ class CsRemoteAccessVpn(CsDataBag):
|
|||
self.confips = []
|
||||
|
||||
logging.debug(self.dbag)
|
||||
|
||||
for public_ip in self.dbag:
|
||||
if public_ip == "id":
|
||||
continue
|
||||
|
|
@ -665,12 +670,13 @@ class CsRemoteAccessVpn(CsDataBag):
|
|||
|
||||
#Enable remote access vpn
|
||||
if vpnconfig['create']:
|
||||
shutdownIpsec = False
|
||||
logging.debug("Enabling remote access vpn on "+ public_ip)
|
||||
|
||||
dev = CsHelper.get_device(public_ip)
|
||||
if dev == "":
|
||||
logging.error("Request for ipsec to %s not possible because ip is not configured", public_ip)
|
||||
continue
|
||||
logging.error("Request for ipsec to %s not possible because ip is not configured", public_ip)
|
||||
continue
|
||||
|
||||
CsHelper.start_if_stopped("ipsec")
|
||||
self.configure_l2tpIpsec(public_ip, self.dbag[public_ip])
|
||||
|
|
@ -682,7 +688,6 @@ class CsRemoteAccessVpn(CsDataBag):
|
|||
CsHelper.execute("ipsec rereadsecrets")
|
||||
else:
|
||||
logging.debug("Disabling remote access vpn .....")
|
||||
#disable remote access vpn
|
||||
CsHelper.execute("ipsec down L2TP-PSK")
|
||||
CsHelper.execute("systemctl stop xl2tpd")
|
||||
|
||||
|
|
@ -693,7 +698,6 @@ class CsRemoteAccessVpn(CsDataBag):
|
|||
xl2tpdconffile="/etc/xl2tpd/xl2tpd.conf"
|
||||
xl2tpoptionsfile='/etc/ppp/options.xl2tpd'
|
||||
|
||||
file = CsFile(l2tpconffile)
|
||||
localip=obj['local_ip']
|
||||
localcidr=obj['local_cidr']
|
||||
publicIface=obj['public_interface']
|
||||
|
|
@ -701,13 +705,13 @@ class CsRemoteAccessVpn(CsDataBag):
|
|||
psk=obj['preshared_key']
|
||||
|
||||
#left
|
||||
file.addeq(" left=%s" % left)
|
||||
file.commit()
|
||||
|
||||
l2tpfile = CsFile(l2tpconffile)
|
||||
l2tpfile.addeq(" left=%s" % left)
|
||||
l2tpfile.commit()
|
||||
|
||||
secret = CsFile(vpnsecretfilte)
|
||||
secret.empty()
|
||||
secret.addeq(": PSK \"%s\"" %psk)
|
||||
secret.addeq("%s %%any : PSK \"%s\"" % (left, psk))
|
||||
secret.commit()
|
||||
|
||||
xl2tpdconf = CsFile(xl2tpdconffile)
|
||||
|
|
@ -730,6 +734,8 @@ class CsRemoteAccessVpn(CsDataBag):
|
|||
self.fw.append(["", "", "-A INPUT -i %s --dst %s -p udp -m udp --dport 1701 -j ACCEPT" % (publicdev, publicip)])
|
||||
self.fw.append(["", "", "-A INPUT -i %s -p ah -j ACCEPT" % publicdev])
|
||||
self.fw.append(["", "", "-A INPUT -i %s -p esp -j ACCEPT" % publicdev])
|
||||
self.fw.append(["", "", "-A OUTPUT -p ah -j ACCEPT"])
|
||||
self.fw.append(["", "", "-A OUTPUT -p esp -j ACCEPT"])
|
||||
|
||||
if self.config.is_vpc():
|
||||
self.fw.append(["", ""," -N VPN_FORWARD"])
|
||||
|
|
|
|||
|
|
@ -142,7 +142,6 @@ ipsec_tunnel_add() {
|
|||
sudo echo "conn vpn-$rightpeer" > $vpnconffile &&
|
||||
sudo echo " left=$leftpeer" >> $vpnconffile &&
|
||||
sudo echo " leftsubnet=$leftnet" >> $vpnconffile &&
|
||||
sudo echo " leftnexthop=$leftnexthop" >> $vpnconffile &&
|
||||
sudo echo " right=$rightpeer" >> $vpnconffile &&
|
||||
sudo echo " rightsubnets={$rightnets}" >> $vpnconffile &&
|
||||
sudo echo " type=tunnel" >> $vpnconffile &&
|
||||
|
|
@ -152,9 +151,8 @@ ipsec_tunnel_add() {
|
|||
sudo echo " ikelifetime=${ikelifetime}s" >> $vpnconffile &&
|
||||
sudo echo " esp=$esppolicy" >> $vpnconffile &&
|
||||
sudo echo " salifetime=${esplifetime}s" >> $vpnconffile &&
|
||||
sudo echo " pfs=$pfs" >> $vpnconffile &&
|
||||
sudo echo " keyingtries=2" >> $vpnconffile &&
|
||||
sudo echo " auto=start" >> $vpnconffile &&
|
||||
sudo echo " auto=route" >> $vpnconffile &&
|
||||
sudo echo "$leftpeer $rightpeer: PSK \"$secret\"" > $vpnsecretsfile &&
|
||||
sudo chmod 0400 $vpnsecretsfile
|
||||
|
||||
|
|
@ -291,12 +289,6 @@ do
|
|||
done < /tmp/iflist
|
||||
|
||||
rightnets=${rightnets//,/ }
|
||||
pfs="no"
|
||||
echo "$esppolicy" | grep "modp" > /dev/null
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
pfs="yes"
|
||||
fi
|
||||
|
||||
ret=0
|
||||
#Firewall ports for one-to-one/static NAT
|
||||
|
|
|
|||
|
|
@ -50,8 +50,6 @@ echo $processname >> $configFile
|
|||
echo $service_name >> $configFile
|
||||
echo $pidfile >> $configFile
|
||||
|
||||
|
||||
|
||||
done
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,9 @@
|
|||
#ipsec remote access vpn configuration
|
||||
conn L2TP-PSK
|
||||
authby=psk
|
||||
pfs=no
|
||||
authby=secret
|
||||
rekey=no
|
||||
keyingtries=3
|
||||
keyexchange=ikev1
|
||||
forceencaps=yes
|
||||
leftfirewall=yes
|
||||
leftnexthop=%defaultroute
|
||||
type=transport
|
||||
#
|
||||
# ----------------------------------------------------------
|
||||
|
|
@ -19,7 +15,7 @@ conn L2TP-PSK
|
|||
#
|
||||
left=172.26.0.151
|
||||
#
|
||||
leftprotoport=17/1701
|
||||
leftprotoport=udp/l2tp
|
||||
# If you insist on supporting non-updated Windows clients,
|
||||
# you can use: leftprotoport=17/%any
|
||||
#
|
||||
|
|
@ -31,10 +27,10 @@ conn L2TP-PSK
|
|||
# If you want to allow multiple connections from any IP address,
|
||||
# you can use: right=%any
|
||||
#
|
||||
rightprotoport=17/%any
|
||||
rightprotoport=udp/%any
|
||||
#
|
||||
# ----------------------------------------------------------
|
||||
# Change 'ignore' to 'add' to enable this configuration.
|
||||
#
|
||||
rightsubnetwithin=0.0.0.0/0
|
||||
auto=add
|
||||
auto=route
|
||||
|
|
|
|||
|
|
@ -4,11 +4,9 @@ ipcp-accept-remote
|
|||
noccp
|
||||
idle 1800
|
||||
auth
|
||||
crtscts
|
||||
mtu 1410
|
||||
mru 1410
|
||||
nodefaultroute
|
||||
debug
|
||||
lock
|
||||
connect-delay 5000
|
||||
ms-dns 10.1.1.1
|
||||
|
|
|
|||
|
|
@ -87,15 +87,15 @@ iptables_() {
|
|||
}
|
||||
|
||||
start_ipsec() {
|
||||
service ipsec status > /dev/null
|
||||
systemctl is-active ipsec > /dev/null
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
service ipsec start > /dev/null
|
||||
systemctl start ipsec > /dev/null
|
||||
#Wait until ipsec started, 5 seconds at most
|
||||
for i in {1..5}
|
||||
do
|
||||
logger -t cloud "$(basename $0): waiting ipsec start..."
|
||||
service ipsec status > /dev/null
|
||||
systemctl is-active ipsec > /dev/null
|
||||
result=$?
|
||||
if [ $result -eq 0 ]
|
||||
then
|
||||
|
|
@ -104,7 +104,7 @@ start_ipsec() {
|
|||
sleep 1
|
||||
done
|
||||
fi
|
||||
service ipsec status > /dev/null
|
||||
systemctl is-active ipsec > /dev/null
|
||||
return $?
|
||||
}
|
||||
|
||||
|
|
@ -112,14 +112,14 @@ ipsec_server() {
|
|||
local op=$1
|
||||
case $op in
|
||||
"start") start_ipsec
|
||||
sudo service xl2tpd start
|
||||
sudo systemctl start xl2tpd
|
||||
;;
|
||||
"stop") sudo service xl2tpd stop
|
||||
"stop") sudo systemctl stop xl2tpd
|
||||
;;
|
||||
"restart") start_ipsec
|
||||
sudo ipsec auto --rereadall
|
||||
service xl2tpd stop
|
||||
service xl2tpd start
|
||||
systemctl stop xl2tpd
|
||||
systemctl start xl2tpd
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
|
@ -131,7 +131,7 @@ create_l2tp_ipsec_vpn_server() {
|
|||
local local_ip=$4
|
||||
|
||||
sed -i -e "s/left=.*$/left=$public_ip/" /etc/ipsec.d/l2tp.conf
|
||||
echo ": PSK \"$ipsec_psk\"" > /etc/ipsec.d/ipsec.any.secrets
|
||||
echo "$public_ip %any : PSK \"$ipsec_psk\"" > /etc/ipsec.d/ipsec.any.secrets
|
||||
sed -i -e "s/^ip range = .*$/ip range = $client_range/" /etc/xl2tpd/xl2tpd.conf
|
||||
sed -i -e "s/^local ip = .*$/local ip = $local_ip/" /etc/xl2tpd/xl2tpd.conf
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ from marvin.codes import PASS, FAILED
|
|||
from marvin.cloudstackTestCase import cloudstackTestCase
|
||||
from marvin.lib.utils import (validateList,
|
||||
cleanup_resources,
|
||||
get_process_status)
|
||||
get_process_status,
|
||||
wait_until)
|
||||
|
||||
from marvin.lib.base import (Domain,
|
||||
Account,
|
||||
|
|
@ -184,7 +185,7 @@ class Services:
|
|||
},
|
||||
"vpn": {
|
||||
"vpn_user": "root",
|
||||
"vpn_pass": "Md1s#dc",
|
||||
"vpn_pass": "Md1sdc",
|
||||
"vpn_pass_fail": "abc!123", # too short
|
||||
"iprange": "10.3.2.1-10.3.2.10",
|
||||
"fordisplay": "true"
|
||||
|
|
@ -757,8 +758,19 @@ class TestVpcSite2SiteVpn(cloudstackTestCase):
|
|||
self.apiclient, customer2_response.id, vpn1_response['id'])
|
||||
self.debug("VPN connection created for VPC %s" % vpc1.id)
|
||||
|
||||
self.assertEqual(
|
||||
vpnconn2_response['state'], "Connected", "Failed to connect between VPCs!")
|
||||
def checkVpnConnected():
|
||||
connections = Vpn.listVpnConnection(
|
||||
self.apiclient,
|
||||
listall='true',
|
||||
vpcid=vpc2.id)
|
||||
if isinstance(connections, list):
|
||||
return connections[0].state == 'Connected', None
|
||||
return False, None
|
||||
|
||||
# Wait up to 60 seconds for passive connection to show up as Connected
|
||||
res, _ = wait_until(2, 30, checkVpnConnected)
|
||||
if not res:
|
||||
self.fail("Failed to connect between VPCs, see VPN state as Connected")
|
||||
|
||||
# acquire an extra ip address to use to ssh into vm2
|
||||
try:
|
||||
|
|
@ -793,9 +805,9 @@ class TestVpcSite2SiteVpn(cloudstackTestCase):
|
|||
|
||||
if ssh_client:
|
||||
# run ping test
|
||||
packet_loss = ssh_client.execute(
|
||||
"/bin/ping -c 3 -t 10 " + vm1.nic[0].ipaddress + " |grep packet|cut -d ' ' -f 7| cut -f1 -d'%'")[0]
|
||||
self.assert_(int(packet_loss) == 0, "Ping did not succeed")
|
||||
packet_loss = ssh_client.execute("/bin/ping -c 3 -t 10 " + vm1.nic[0].ipaddress + " | grep packet | sed 's/.*received, //g' | sed 's/[% ]*packet.*//g'")[0]
|
||||
# during startup, some packets may not reply due to link/ipsec-route setup
|
||||
self.assert_(int(packet_loss) < 50, "Ping did not succeed")
|
||||
else:
|
||||
self.fail("Failed to setup ssh connection to %s" % vm2.public_ip)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue