Multiple Local Subnets for VPNaaS

As originally implemented, an VPN IPSec connection could have one or more peer subnets specified, but only one local subnet. To support multiple local subnets, multiple IPSec connections would be needed.

With the multiple local subnet support, three goals are addressed. First, there can be multiple local and peer endpoints for a single IPSec connection.

Second, validation enforces that the same IP version is used for all endpoints (to reduce complexity and ease testing).

Third, the “what is connected” is separated from the “how to connect”, so that other flavors of VPN (as they are developed) can use some of this mechanism.

Design Notes

There were three proposals considered, to support multiple local subnets.

Proposal A was to just add the local subnets to the IPSec connection API. That would be the quickest way, and addresses the first two goals, but not the third.

Proposal B was to create a new API that specifies of the local subnets and peer CIDRs, and reference those in the connection API. This would separate the “what is connected” from the “how to connect”, and again addresses the first two goals (only).

Proposal C, which was the selected proposal, creates a new API that represents the “endpoint groups” for VPN connections, in the same manner as proposal B. The added flexibility here, though, which meets goal three, is to also include the endpoint group “type”, thus allowing subnets (local) and CIDRs (peer) to be used for IPSec, but routers, networks, and VLANs to be used for other VPN types (BGP, L2, direct connection). Additional types can be added in the future as needed.

Client CLI API

The originally implemented client CLI APIs (which are still available for backward compatibility) for an IPsec connection are:

neutron vpn-service-create ROUTER SUBNET
neutron ipsec-site-connection-create
   --vpnservice-id VPNSERVICE
    --ikepolicy-id IKEPOLICY
    --ipsecpolicy-id IPSECPOLICY
    --peer-address PEER_ADDRESS
    --peer-id PEER_ID
    --peer-cidr PEER_CIDRS
    --dpd action=ACTION,interval=INTERVAL,timeout=TIMEOUT
    --initiator {bi-directional | response-only}
    --mtu MTU
    --psk PSK

Changes to the API, to support multiple local subnets, are shown in bold text:

neutron vpn-service-create ROUTER
**neutron vpn-endpoint-groups-create**
    **--name OPTIONAL-NAME**
    **--description OPTIONAL-DESCRIPTION**
    **--ep-type={subnet,cidr,network,vlan,router}**
    **--ep-value=[list-of-endpoints-of-type]**
neutron ipsec-site-connection-create
    --vpnservice-id VPNSERVICE
    --ikepolicy-id IKEPOLICY
    --ipsecpolicy-id IPSECPOLICY
    --peer-address PEER_ADDRESS
    --peer-id PEER_ID
    --dpd action=ACTION,interval=INTERVAL,timeout=TIMEOUT
    --initiator {bi-directional | response-only}
    --mtu MTU
    --psk PSK
    **--local-endpoints ENDPOINT-GROUPS-UUID**
    **--peer-endpoints ENDPOINT-GROUPS-UUID**

The SUBNET in the original service API is optional, and will be used as an indicator of whether or not the multiple local subnets feature is active. See the ‘Backward Compatibility’ section, below, for details.

For the endpoint groups, the –ep-type value is a string, so that other types can be supported in the future.

The endpoint groups API would enforce that the endpoint values are all of the same type, and match the endpoint type specified.

The connection APIs, would then provide additional validation. For example, with IPSec, the endpoint type must be ‘subnet’ for local, and ‘cidr’ for peer, all the endpoints should be of the same IP version, and for the local endpoint, all subnets would be on the same router.

For BGP VPN with dynamic routing, only a local endpoint group would be specified, and the type would be ‘network’.

The ROUTER may also be able to be removed, in the future, and can be determined, when the connections are created.

Note: Using –ep-type, as –endpoint-type is already used elsewhere, and –type is too generic. Using –ep-value, as –endpoint is already in use, –end-point could be easily mistyped as –endpoint, and –value is too generic.

Examples

The original APIs to create one side of an IPSec connection with only one local and peer subnet:

neutron vpn-ikepolicy-create ikepolicy
neutron vpn-ipsecpolicy-create ipsecpolicy
neutron vpn-service-create --name myvpn router1 privateA
neutron ipsec-site-connection-create
    --name vpnconnection1
    --vpnservice-id myvpn
    --ikepolicy-id ikepolicy
    --ipsecpolicy-id ipsecpolicy
    --peer-address 172.24.4.13
    --peer-id 172.24.4.13
    --peer-cidr 10.3.0.0/24
    --psk secret

The local CIDR is obtained from the subnet, privateA. In this example, that would be 10.1.0.0/24 (because that’s how privateA was created).

Using the multiple local subnet feature, the APIs (with changes shown in bold below:

neutron vpn-ikepolicy-create ikepolicy
neutron vpn-ipsecpolicy-create ipsecpolicy
neutron vpn-service-create --name myvpn router1
**neutron vpn-endpoint-group-create**
    **--name local-eps**
    **--ep-type=subnet**
    **--ep-value=privateA**
    **--ep-value=privateB**
**neutron vpn-endpoint-group-create**
    **--name peer-eps**
    **--ep-type=cidr**
    **--ep-vallue=10.3.0.0/24**
neutron ipsec-site-connection-create
    --name vpnconnection1
    --vpnservice-id myvpn
    --ikepolicy-id ikepolicy
    --ipsecpolicy-id ipsecpolicy
    --peer-address 172.24.4.13
    --psk secret
    **--local-endpoints local-eps**
    **--peer-endpoints peer-eps**

The subnets privateA and privateB are used for local endpoints and the 10.3.0.0/24 CIDR is used for the peer endpoint.

Database

The vpn_endpoints table contains single endpoint entries and a reference to the containing endpoint group. The vpn_endpoint_groups table defines the group, specifying the endpoint type.

Database Migration

For an older database, the first subnet, in the subnet entry of the service table can be placed in an endpoint group that will be used for the local endpoints of the connection. The CIDRs from the connection can be placed into another endpoint group for the peer endpoints.

Backwards Compatibility

Operators would like to see this new capability provided, with backward compatibility support. The implication, as I see it, is to provide the ability for end users to be able to switch to the new API at any time, versus being forced to use the new API immediately, upon upgrade to the new release containing this feature. This would apply to both manual API use, and client apps/scripting-tools that would be used to configure VPNaaS.

There are several attributes that are involve here. One is the subnet ID attribute in the VPN service API. The other is the peer CIDR attribute in the IPSec connection API. Both would be specified by endpoint groups in the new API, and these groups would be called out in the IPSec connection API.

A plan to meet the backward compatibility goal of allowing both APIs to be used at once involves taking the following steps.

For VPN service:

  • Make the subnet ID attribute optional.
  • If subnet ID is specified for create, consider old API mode.
  • If subnet ID specified for create, create endpoint group and store ID.
  • For delete, if subnet ID exists, delete corresponding endpoint group.
  • For show/list, if subnet ID exists, show the ID in output.
  • Subnet ID is not mutable, so no change for update API.

For IPSec site to site connection:

  • For create, if old API mode, only allow peer-cidr attribute.
  • For create, if not old API mode, require local/peer endpoint group IDs attributes.
  • For create, if peer-cidr specified, create endpoint group and store ID.
  • For create, reject endpoint group ID attributes, if old API mode.
  • For create, reject peer-cidr attribute, if not old API mode.
  • For create, if old API mode, lookup subnet in service, find containing endpoint group ID and store.
  • For delete, if old API mode, delete endpoint group for peer.
  • For update of CIDRs (old mode), will delete endpoint group and create new one. (note 1)
  • For update of endpoint-group IDs (new mode), will allow different groups to be specified. (note 1,2)
  • For show/list, if old API mode, only display the peer CIDR values from peer endpoint group.
  • For show/list, if not old API mode, also show local subnets from local endpoint group.

Note 1: Implication is that connection is torn down and re-created (as is done currently).

Note 2: Users would create a new endpoint group, and then select that group, when modifying the IPSec connection.

For endpoint groups:

  • For delete, if subnet, and (sole) subnet ID is used in a VPN service (old mode), reject request.
  • Updates are not supported, so no action required. (note 2)

Note 2: Allowing updates would require deletion/recreation of connection using endpoint group. Avoiding that complexity.

The thought here is to use endpoint groups under the hood, but if the old API was being used, treat the endpoint groups as if they never existed. Deleting connections and services would remove any endpoint groups, unlike with the new API, where they are independent.

Migration can be used to move any VPNaaS configurations using the old schema to the new schema. This would look at VPN services and for any with a subnet ID, an endpoint group would be created and the group ID stored in any existing IPSec connections for that service. Likewise, any peer CIDRs in a connection would be copied into a new endpoint group and the group ID stored in the connection.

The subnet ID field would then be removed from the VPN service table, and the peer CIDRs table would be removed.

This migration could be done at the time of the new API release, in which case all tenants with existing VPNaaS configurations would use the new API to manage them (but could use old for new configurations).

Alternatively, the migration could be deferred until the old API is removed, to ensure all existing configurations conform to the new schema. Migration tools can then be created to manually migrate individual tenants, as desired.

Stories

For the endpoint groups, stories can cover:

  • CRUD API for the endpoint groups.
  • Database support for new tables.
  • Migration creation of new tables.
  • Validation of endpoints for a group (same type).
  • Neutron client support for new API.
  • Horizon support for new API.
  • API documentation update.

For the multiple local subnets, stories can cover:

  • create IPsec connection with one local subnet, but using new API.
  • create IPSec connection with multiple local subnets.
  • Show IPSec connection to display endpoint group IDs (or endpoints?).
  • Ensure previous API still works, but uses new tables.
  • Validation to ensure old and new APIs are not mixed.
  • Modify CLI client.
  • Validate multiple local subnets on same router.
  • Validate local and peer endpoints are of same IP version.
  • Functional tests with multiple local subnets
  • API and How-To documentation update

Note: The intent here is to have the initial stories take slices vertically through the process so that we can demonstrate the capability early.

Note: Horizon work to support the changes is not expected to be part of this effort and would be handled by the Horizon team separately, if support is desired.