apache / apache/cloudstack

Support site-to-site VPN customer gateway with dynamic peer IP (authentication by ID)

Open
#13,512 2 comments 0 reactions 0 assignees View on GitHub
component:api component:UI component:virtual-router
Dominant language
Java
Stars
3.1k
Forks
1.4k
Avg merge
6d 19h
Merged PRs (30d)
32

Description

### The required feature described as a wish

Support site-to-site VPN customer gateway with dynamic peer IP (authentication by ID)

##### ISSUE TYPE

* Enhancement Request

##### COMPONENT NAME

~~~
Component:api
Component:UI
Component:systemvm (Virtual Router / strongSwan)
~~~

##### CLOUDSTACK VERSION

~~~
4.22.0.0
~~~

##### SUMMARY

Today a VPN Customer Gateway requires a fixed, resolvable peer IP/FQDN in the
`Gateway` field. This makes it impossible to terminate a site-to-site IPsec
tunnel against a remote endpoint that has a **dynamic public IP** (a very common
case: branch offices / remote sites behind a consumer or SME ISP link with no
static IP), where the remote peer must instead be identified by an **IKE
identity (ID)** rather than by its source IP.

The underlying engine (strongSwan on the VR) fully supports this scenario via
`right=%any` + `rightid=`. The limitation is purely in the CloudStack
orchestration layer, which models and identifies the peer by IP only.

It would be valuable to allow a Customer Gateway to be created **without a fixed
peer IP**, identifying the remote peer by an ID instead, so the VR acts as a pure
responder for a dynamic-IP peer.

##### CURRENT BEHAVIOUR

When the remote site has no static IP, there is no supported way to configure
the tunnel:

* The `Gateway` field validates the input as an IP/FQDN and rejects anything
that is not a single resolvable address. For example, entering `0.0.0.0/0`
returns:

~~~
The customer gateway ip/Domain 0.0.0.0/0 is invalid!
~~~

* If a Customer Gateway ends up with a null/`0.0.0.0` peer, the VR
(`CsSite2SiteVpn` in `systemvm/debian/opt/cloud/bin/configure.py`) generates a
broken configuration:
* the strongSwan connection is written with `right=0.0.0.0` and `auto=route`,
which makes charon try to *initiate/route* toward a null address
(`installing trap failed, remote address unknown` in `charon` log);
* the INPUT firewall rule for IKE/ESP is generated with `-s 0.0.0.0`
(the null host, which matches no real packet) instead of `-s 0.0.0.0/0`
(any), so the remote peer's IKE packets are silently dropped by the
`INPUT DROP` policy before reaching charon.

* There is no field on the Customer Gateway to declare a remote **ID**. When we manually open the INPUT firewall, the session establishes without identity verification.

Net result: a dynamic-IP, ID-authenticated remote peer cannot be configured
through the UI/API at all.

##### EXPECTED BEHAVIOUR

Allow a Customer Gateway to represent a **dynamic-IP peer**:

* Make the peer `Gateway` IP optional **when** a remote ID / peer identity is
provided (new field). The remote ID replaces the IP as the peer's
authentication identity (IKE ID types: IPv4/IPv6 address, FQDN, RFC822/email,
or DN).
* On the VR, when the peer is dynamic, `CsSite2SiteVpn` should generate:
* `right=%any`
* `rightid=`
* `auto=add` (responder only — the VR cannot initiate toward an unknown IP)
* the PSK indexed by the remote **ID** in `ipsec.*.secrets` (not by IP)
* an INPUT firewall rule opening UDP/500, UDP/4500 and ESP (proto 50) toward
the source-NAT IP, either with `-s 0.0.0.0/0` or restricted to an
operator-supplied source range (possibly a list)
* Reuse the existing **Passive** mode semantics (the VR already supports waiting
for the remote side to initiate, used today for VPC-to-VPC), since a dynamic
peer is inherently the initiator.

This has been validated manually on a 4.22 VR (strongSwan 5.9.8): with
`right=%any` / `rightid=` / PSK-by-ID and the INPUT rule opened, an IKEv2
tunnel from a dynamic-IP peer authenticating by ID establishes correctly and
passes traffic both ways (`ESTABLISHED` + `INSTALLED, TUNNEL`, bidirectional
`bytes_i` / `bytes_o`). The only blocker to native support is the orchestration
layer.

##### PROPOSED IMPLEMENTATION (for discussion)

* **API / DB / UI**: add an optional `remoteid` (peer identity) attribute to
Create/Update VPN Customer Gateway; make `gateway` optional when `remoteid`
is set; expose a clear "dynamic peer IP" indication in the UI.
* **VR (`CsSite2SiteVpn` in `configure.py`)**: branch on dynamic peer to emit
`right=%any`, `rightid`, `auto=add`, PSK-by-ID, and the open INPUT rule.
* **Tests**: extend `test/integration/smoke/test_vpc_vpn.py` with a
dynamic-peer / responder case.

##### SECURITY CONSIDERATIONS

Because a dynamic peer cannot be filtered by source IP, this mode opens
UDP/500 + UDP/4500 + ESP on the public interface. To keep this safe
and explicit:

* the feature should be **opt-in** (an explicit "dynamic peer" flag on the
Customer Gateway), never a silent fallback;
* `rightid` should be **mandatory** in this mode so the peer is constrained to a
known identity;
* IKEv2 should be used (no PSK-hash exposure, unlike IKEv1 aggressive mode);
* the UI should warn that the PSK becomes the primary authentication barrier and
must be long and random;
* optionally allow restricting the INPUT rule to an operator-supplied source
CIDR (e.g. the remote ISP's known range) instead of `0.0.0.0/0`. As operators oftens have multiple CIDR a list of CIDR would be better.

##### ENVIRONMENT (where observed)

~~~
CloudStack 4.22.0.0
System VM template: systemvm-kvm-4.22.0-x86_64
Virtual Router strongSwan: 5.9.8
Tunnel: IKEv2, PSK, remote peer behind NAT with dynamic public IP,
authenticating by RFC822-style ID
~~~

Contributor guide

Open the contributing guide

Research direction

Start with the Customer Gateway Create/Update API, database and UI paths, then read CsSite2SiteVpn in systemvm/debian/opt/cloud/bin/configure.py to trace current peer and firewall generation. Review test/integration/smoke/test_vpc_vpn.py and the proposed dynamic-peer responder case. Done means an explicit dynamic-peer gateway accepts a remote ID and produces the described responder configuration, firewall behavior, and passing integration coverage.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, python
Domain
infrastructure, networking, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.