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.
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.
| Mode | What it does | Source address | Choose it when |
|---|---|---|---|
| CloudAddress | One public address, transferred to one device. The device wears it; nothing is NATed. | Not translated: the device wears the address | One machine outside the cloud needs a cloud IP of its own |
| CloudVpc | The device joins the relay's private network and wears its VPC address. | Not translated: the device wears a VPC address | Compute outside the VPC must behave as a member of it |
| CloudVpn | Several devices share one public address. The only mode that NATs. | Translated to the shared address | A team should reach the internet from one cloud IP |
| CloudConnector | An L3 pipe between clouds. Forwards with the source intact -- no NAT, no address transfer. | Not translated: the original source crosses | Two 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
| Component | Where it runs | What it does |
|---|---|---|
| AWS relay fleet | Your AWS account: one Auto Scaling group per Availability Zone, behind a Gateway Load Balancer with one GWLB endpoint per zone | Takes 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 fleet | Your Google Cloud project: a regional managed instance group behind an internal passthrough Network Load Balancer | The same, for VMs that carry the pipe's client network tag |
| Controller | Your AWS account: an Auto Scaling group of exactly one instance holding an Elastic IP, with its state in a DynamoDB table | Stores 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 configuration | Stored on the controller, written by Terraform | Names the two sides and the IPv4 ranges reachable through each |
The path of a packet
- 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.
- 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.
- 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.
- 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 A | End B | Status in 1.0.0 |
|---|---|---|
| AWS | Google Cloud | Supported: the deployment roots build exactly this pair |
| Any other pair | Not supported in this release | |
Both ends run on amd64 or arm64; the architecture is one input and the instance types follow from it:
| Architecture | AWS relay | Google Cloud relay |
|---|---|---|
amd64 (default) | c5n.large | n2-standard-4 |
arm64 | c6gn.medium | t2a-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/gatewayprovider, plus thehashicorp/aws,hashicorp/googleandhashicorp/randomproviders. - 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.
| Lane | Price | Terms that matter for a pipe |
|---|---|---|
| Developer | $10 per vCPU-month | Development, 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-month | Production 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
| Limit | Value |
|---|---|
| Sides per pipe | Exactly two: one AWS end and one Google Cloud end |
| Advertised ranges | IPv4 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 with | 32. Beyond that, the highest-numbered far relays carry no traffic. |
| Relays per side | At 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 MTU | 1380 bytes; TCP MSS is clamped to 1340 |
| TTL on the far side | Packets leave the pipe with a TTL of at most 16 |
| Sizing | 3 Gbps per relay; a single conversation is carried by one relay |
| Developer lane | 16 raw vCPUs per account, all relays together |
| Enterprise lane | At least 4 vCPUs per relay instance |
The full list of known limitations is at the end of the FAQ.