You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by bh...@apache.org on 2017/12/02 15:45:41 UTC

[cloudstack] 08/09: CLOUDSTACK-10013: Fix ipsec VPN configuration

This is an automated email from the ASF dual-hosted git repository.

bhaisaab pushed a commit to branch debian9-systemvmtemplate
in repository https://gitbox.apache.org/repos/asf/cloudstack.git

commit d851cf409dc74c43a1796dd9601022dd8e1fdef7
Author: Rohit Yadav <ro...@shapeblue.com>
AuthorDate: Fri Dec 1 20:58:18 2017 +0530

    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 <ro...@shapeblue.com>
---
 systemvm/patches/debian/opt/cloud/bin/configure.py | 38 +++++++++++++---------
 .../patches/debian/opt/cloud/bin/ipsectunnel.sh    | 10 +-----
 .../debian/opt/cloud/bin/monitor_service.sh        |  2 --
 systemvm/patches/vpn/etc/ipsec.d/l2tp.conf         | 12 +++----
 systemvm/patches/vpn/etc/ppp/options.xl2tpd        |  2 --
 systemvm/patches/vpn/opt/cloud/bin/vpn_l2tp.sh     | 18 +++++-----
 test/integration/smoke/test_vpc_vpn.py             | 26 +++++++++++----
 7 files changed, 55 insertions(+), 53 deletions(-)

diff --git a/systemvm/patches/debian/opt/cloud/bin/configure.py b/systemvm/patches/debian/opt/cloud/bin/configure.py
index 68d1c26..b8a3e02 100755
--- a/systemvm/patches/debian/opt/cloud/bin/configure.py
+++ b/systemvm/patches/debian/opt/cloud/bin/configure.py
@@ -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"])
diff --git a/systemvm/patches/debian/opt/cloud/bin/ipsectunnel.sh b/systemvm/patches/debian/opt/cloud/bin/ipsectunnel.sh
index 20caec5..c42650f 100755
--- a/systemvm/patches/debian/opt/cloud/bin/ipsectunnel.sh
+++ b/systemvm/patches/debian/opt/cloud/bin/ipsectunnel.sh
@@ -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
diff --git a/systemvm/patches/debian/opt/cloud/bin/monitor_service.sh b/systemvm/patches/debian/opt/cloud/bin/monitor_service.sh
index d9d8ec8..e1c7914 100755
--- a/systemvm/patches/debian/opt/cloud/bin/monitor_service.sh
+++ b/systemvm/patches/debian/opt/cloud/bin/monitor_service.sh
@@ -50,8 +50,6 @@ echo $processname >> $configFile
 echo $service_name >> $configFile
 echo $pidfile >> $configFile
 
-
-
 done
 
 }
diff --git a/systemvm/patches/vpn/etc/ipsec.d/l2tp.conf b/systemvm/patches/vpn/etc/ipsec.d/l2tp.conf
index 1cbfe78..2e211e1 100644
--- a/systemvm/patches/vpn/etc/ipsec.d/l2tp.conf
+++ b/systemvm/patches/vpn/etc/ipsec.d/l2tp.conf
@@ -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
diff --git a/systemvm/patches/vpn/etc/ppp/options.xl2tpd b/systemvm/patches/vpn/etc/ppp/options.xl2tpd
index 08c301b..a01687f 100644
--- a/systemvm/patches/vpn/etc/ppp/options.xl2tpd
+++ b/systemvm/patches/vpn/etc/ppp/options.xl2tpd
@@ -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
diff --git a/systemvm/patches/vpn/opt/cloud/bin/vpn_l2tp.sh b/systemvm/patches/vpn/opt/cloud/bin/vpn_l2tp.sh
index 60ee8a6..5928548 100755
--- a/systemvm/patches/vpn/opt/cloud/bin/vpn_l2tp.sh
+++ b/systemvm/patches/vpn/opt/cloud/bin/vpn_l2tp.sh
@@ -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
 
diff --git a/test/integration/smoke/test_vpc_vpn.py b/test/integration/smoke/test_vpc_vpn.py
index ddf7693..83c244b 100644
--- a/test/integration/smoke/test_vpc_vpn.py
+++ b/test/integration/smoke/test_vpc_vpn.py
@@ -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"
@@ -756,8 +757,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:
@@ -792,9 +804,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)
 

-- 
To stop receiving notification emails like this one, please contact
"commits@cloudstack.apache.org" <co...@cloudstack.apache.org>.