CloudConnector -- Overview v1.0.0

An L3 pipe between clouds. Forwards with the source intact -- no NAT, no address transfer.

CloudConnector joins a VPC in AWS to a VPC in Google Cloud at layer 3. Hosts on either side reach the other side by its private addresses, and every packet arrives carrying the address of the host that sent it: nothing is NATed and no address is handed over. It is one of the four modes of the relay that ships inside Cloud Spectra Gateway, and everything it runs -- relays, load balancers, the controller -- runs in your own cloud accounts.

Where to go next: the Quick Start builds a pipe between a new AWS VPC and a new Google Cloud network with Terraform; the User Guide covers configuration, routing, scaling and operations; the FAQ ends with the known limitations of this release.

What CloudConnector is

Each side of the pipe runs a fleet of relays -- ordinary instances in your account, behind that cloud's own load balancer. Every relay keeps an encrypted WireGuard tunnel to every relay on the far side, and a controller in your AWS account tells each relay which side it is on and who is on the other side. Your route tables send traffic for the far side's ranges to the local relays; the relays carry it across and deliver it to the destination host unchanged.

What that gives you:

  • Private addressing across clouds. A service in AWS calls a database in Google Cloud at its private address, and the reverse.
  • The real source on every packet. The far side's firewall rules, security groups and logs see the sending host's own address, so rules written per host or per subnet keep meaning what they say.
  • No circuit to order. Traffic between the clouds crosses the internet inside WireGuard tunnels between your own relays.
  • Capacity that follows the fleet. Each relay is sized as 3 Gbps of pipe; add relays on both sides and the pipe can carry more flows in parallel.

In Terraform and on the wire the mode is called cloud_connector.

CloudConnector or another mode?

The relay has four modes. They build different infrastructure, so the mode is always stated explicitly: an intent without one is refused at plan time rather than defaulted. All four are licensed the same way, per relay vCPU.

ModeWhat it doesSource addressChoose it when
CloudAddressOne public address, transferred to one device. The device wears it; nothing is NATed.Not translated: the device wears the addressOne machine outside the cloud needs a cloud IP of its own
CloudVpcThe device joins the relay's private network and wears its VPC address.Not translated: the device wears a VPC addressCompute outside the VPC must behave as a member of it
CloudVpnSeveral devices share one public address. The only mode that NATs.Translated to the shared addressA team should reach the internet from one cloud IP
CloudConnectorAn L3 pipe between clouds. Forwards with the source intact -- no NAT, no address transfer.Not translated: the original source crossesTwo VPCs in different clouds must reach each other by their private addresses

CloudConnector is the mode with relays at both ends and nothing installed on your workloads: hosts send ordinary IP packets to the other side's private addresses, and the routes you add carry them into the pipe.

How it works

flowchart LR
    subgraph AWS["AWS VPC"]
        direction TB
        HA["Workload
10.60.1.10"] EP["GWLB endpoint
(one per zone)"] RA["Relay fleet
Auto Scaling group per zone
behind a Gateway Load Balancer"] HA -->|"route: Google Cloud range"| EP EP --> RA end subgraph GCP["Google Cloud VPC"] direction TB RG["Relay fleet
regional managed instance group
behind an internal passthrough NLB"] HG["Workload with the client tag
10.70.1.20"] HG -->|"route: AWS range"| RG end RA <-->|"WireGuard bond
every relay to every far-side relay"| RG CTL["Controller
pipe config, relay registry, rosters"] CTL -.->|"register, read far-side roster"| RA CTL -.->|"register, read far-side roster"| RG style AWS fill:#eef2ff,stroke:#6366f1,color:#312e81 style GCP fill:#ecfdf5,stroke:#10b981,color:#065f46 style CTL fill:#fef3c7,stroke:#f59e0b,color:#92400e

Illustrative addresses. A packet from 10.60.1.10 reaches 10.70.1.20 still carrying 10.60.1.10 as its source.

The components

ComponentWhere it runsWhat it does
AWS relay fleetYour AWS account: one Auto Scaling group per Availability Zone, behind a Gateway Load Balancer with one GWLB endpoint per zoneTakes the traffic your route tables send to the GWLB endpoint and forwards it to the far side; delivers traffic arriving from the far side to its destination
Google Cloud relay fleetYour Google Cloud project: a regional managed instance group behind an internal passthrough Network Load BalancerThe same, for VMs that carry the pipe's client network tag
ControllerYour AWS account: an Auto Scaling group of exactly one instance holding an Elastic IP, with its state in a DynamoDB tableStores the pipe configuration, registers relays, places each one on its side and serves each relay the far side's roster. It is not on the data path.
Pipe configurationStored on the controller, written by TerraformNames the two sides and the IPv4 ranges reachable through each

The path of a packet

  1. A host sends to a private address on the far side. Your route delivers the packet to a local relay: on AWS a route-table entry whose target is the zone's GWLB endpoint, on Google Cloud a route for instances with the client tag whose next hop is the internal load balancer. The load balancers are used for ingress only.
  2. The relay's eBPF datapath matches the packet -- source inside this side's ranges, destination inside the far side's -- clamps the TCP MSS to fit the tunnel, hashes the flow onto one member of its bond and sends it through that member's WireGuard tunnel to one far-side relay.
  3. The far-side relay decrypts the packet and hands it straight to the destination host. There is no source NAT anywhere on this path; the destination sees the original sender.
  4. Replies travel the same way in the other direction.

The bond

Each relay holds one WireGuard tunnel -- a bond member -- for every relay on the far side, up to 32. A flow is hashed on its addresses, protocol and ports, the same way in both directions, so every packet of one connection rides the same member and stays in order; different flows spread over the members in proportion to each far relay's capacity, which the controller derives from the relay's instance type. A far relay that stops registering leaves the roster after 90 seconds, and the bond is rebuilt without it.

Two consequences shape capacity planning: one conversation between two hosts enters the pipe through one relay, and the number of members on each relay is the number of relays on the far side -- so the pipe grows when both sides grow. See Sizing and scaling.

Registration and the controller

Every relay registers with the controller every 30 seconds, presenting its side's announce credential. The controller places the relay on the side that credential belongs to -- a relay cannot name its own side -- and each relay reads the far side's roster every 30 seconds: every far relay's endpoint, public key, advertised ranges and weight. A relay that stops registering drops out of the roster after 90 seconds. When the number of relays on the far side changes, a relay rebuilds its bond with a brief restart of its datapath.

If the controller cannot be reached, relays keep forwarding with the roster they already hold. After 300 seconds without a fresh roster they mark it stale and log a warning; they do not tear the pipe down on their own.

Encryption and keys

Relay-to-relay traffic is kernel WireGuard. Each relay generates its own key pair when it first boots and keeps the private key on the instance; only the public key goes to the controller, so no relay private key is ever in Terraform state. Relays also check in with the Cloud Spectra licence service every two minutes and fetch their signed datapath from it at boot; a relay that cannot confirm its licence for 48 hours parks and stops forwarding. Details are in the security model.

Supported clouds

End AEnd BStatus in 1.0.0
AWSGoogle CloudSupported: the deployment roots build exactly this pair
Any other pairNot supported in this release

Both ends run on amd64 or arm64; the architecture is one input and the instance types follow from it:

ArchitectureAWS relayGoogle Cloud relay
amd64 (default)c5n.largen2-standard-4
arm64c6gn.mediumt2a-standard-4

The AWS shapes are network-optimised; on Google Cloud, egress bandwidth scales with vCPU count, so raise the machine size for more. Both can be overridden (see the configuration reference).

Requirements

  • An AWS account and a Google Cloud project with permission to create networking, compute and load-balancing resources (listed in the Quick Start). The Compute Engine API must be enabled in the project.
  • A Cloud Spectra licence key. Both ends run under the same licence.
  • Terraform 1.5 or later with the cloudspectra/gateway provider, plus the hashicorp/aws, hashicorp/google and hashicorp/random providers.
  • Non-overlapping IPv4 ranges. Each side advertises the ranges reachable through it: IPv4 only, at most eight prefixes per side, no 0.0.0.0/0, and no overlap between the two sides.
  • Reachable relays. Every relay needs outbound internet access (to the controller, to the far-side relays and to the Cloud Spectra licence service) and an address the far side can dial: an IPv6 global address or a public IPv4 address. The WireGuard port band, from UDP 28302 upwards, must be open between the two sides.
  • Routes and firewall rules you control. On AWS you add routes to the route tables of your workload subnets; on Google Cloud you tag the VMs that should use the pipe. Because sources are preserved, each side's firewall rules must admit the other side's ranges.

Pricing

CloudConnector is licensed like every Cloud Spectra Gateway feature: per relay vCPU, metered hourly, on both ends of the pipe. Each relay instance bills max(1, min(vCPUs, 64) - 1) vCPUs -- the second vCPU of every instance is free.

LanePriceTerms that matter for a pipe
Developer$10 per vCPU-monthDevelopment, evaluation and personal use. At most 16 raw vCPUs per account across all relays; relays that do not fit are parked until room frees up.
Enterprise$30 per vCPU-monthProduction use. Every relay instance must have at least 4 vCPUs -- so the default AWS relay shapes (c5n.large, c6gn.medium) must be raised.

For example, the smallest pipe -- one c5n.large relay (2 vCPUs, bills 1) and one n2-standard-4 relay (4 vCPUs, bills 3) -- bills 4 vCPUs. The controller is not licensed or metered. Your cloud providers bill the relay and controller instances, the load balancers and endpoints, Cloud NAT, and the data the pipe carries between the clouds as internet egress -- see Cost considerations. Current rates and lane details are on the pricing page.

Limits

LimitValue
Sides per pipeExactly two: one AWS end and one Google Cloud end
Advertised rangesIPv4 only; up to 8 prefixes per side; no /0; the two sides must not overlap, and no range may overlap 169.254.0.0/16 or contain 168.63.129.16
Far-side relays one relay can bond with32. Beyond that, the highest-numbered far relays carry no traffic.
Relays per sideAt most 32 carry traffic; the controller's registry holds 500 entries per fleet
Bond port band (tunnel_members)2-32 ports per relay, starting at UDP 28302
Tunnel MTU1380 bytes; TCP MSS is clamped to 1340
TTL on the far sidePackets leave the pipe with a TTL of at most 16
Sizing3 Gbps per relay; a single conversation is carried by one relay
Developer lane16 raw vCPUs per account, all relays together
Enterprise laneAt least 4 vCPUs per relay instance

The full list of known limitations is at the end of the FAQ.