Skip to content

Providers

BaddKharma edited this page Nov 6, 2026 · 17 revisions

Providers

Node kinds declare what they need (compute, a public address, a Windows or Linux image, outbound routing). Providers declare what they can do. When a topology asks for something the target cannot deliver, the canvas raises an error at design time (CAP001, CAP002, CAP004), which is what keeps one provider from forking into many.

Support matrix

Provider Target ranges Attack infrastructure
GCP Tested Tested
AWS Tested Tested
Azure Tested Tested
Proxmox Roadmap Roadmap
ESXi Roadmap Roadmap

GCP, AWS, and Azure are tested end to end for both target ranges and attack infrastructure. Proxmox and ESXi are on the roadmap, not yet supported.

Azure

What has been deployed and validated on Azure:

  • Attack infrastructure: minimalc2-cli, and the full 8-VM redstack (Mythic, Sliver, and Adaptix teamservers, a collector, a Windows operator, and a Kali operator). Both passed verify.py doors and verify.py stack, with a Let's Encrypt certificate on the redirector.
  • Target ranges: minilab (domain controller promotion over WinRM), goad-light, and goad-wazuh (child domain promotion, the parent and child trust, MSSQL, and the Wazuh manager and agents).
  • Full GOAD and dracarys: both deployed clean and validated. Full GOAD: both forests and the cross-forest trust, ADCS on ESSOS-CA, and MSSQL. dracarys: the KeePass vault and a Linux host joined to the domain.
  • The beacon path: from an Azure offense range, a Sliver beacon launched as patient zero in full GOAD called back through the redirector, and the GOAD playbook checks for recon, AS-REP roasting, Kerberoasting, ADCS enumeration, and MSSQL impersonation ran through it.

Notes that differ from GCP and AWS:

  • One resource group per range. resource_group in deploy.tfvars names it (default {prefix}-{topology name}-rg), and the default location is eastus2. The preflight stops the deploy if that group already exists and this range's Terraform state does not own it.
  • Sizes and quotas are checked before apply. Subscriptions differ in which VM sizes they may use and how many vCPUs each family gets, so deploy.sh runs a read-only preflight and stops before anything is created when the topology will not fit. See Azure sizes and quotas and The Azure preflight in Cloud Prerequisites.
  • Kali. The Kali operator starts from a Debian 13 image and the operator role converts it to Kali, so there is no Marketplace plan to accept, unlike AWS.
  • .NET on Windows Server 2019. Azure's Windows Server 2019 image ships .NET Framework 4.7.2. Where chocolatey needs 4.8 (MSSQL, the KeePass vault), the roles install it.
  • Auto-stop is a Microsoft.DevTestLab per-VM shutdown schedule, which needs that resource provider registered. It takes a Windows timezone id, not an IANA name: the compiler translates common IANA zones (for example America/New_York to Eastern Standard Time) and refuses one it has no mapping for. Use UTC, a mapped zone, or a Windows id such as "GMT Standard Time".
  • Stop deallocates. manage.sh stop deallocates the VMs, which halts compute billing, and the jumpbox keeps its public IP. manage.sh status, start, stop, and teardown --force need the Azure CLI installed and logged in; teardown --force deletes the whole resource group.
  • No poisoning or relay path. Like GCP and AWS, Azure's software-defined network drops L2 broadcast and multicast, which name-resolution poisoning and the relay path need, so llmnr_poisoning, nbtns_poisoning, responder, ntlm_relay, and ldap_signing_off are not planted on any of the three: the canvas greys them out and the compiler skips them.
  • Windows client licensing. Windows 10 and 11 hosts boot Microsoft's client images, which Microsoft licenses on Azure only for customers with a qualifying license. redStackPRO does not set license_type, so eligibility is yours to confirm. See Windows client licensing on Azure in Cloud Prerequisites.

Name resolution is the same on Azure as on GCP and AWS: the export creates no managed private DNS zone on any provider, so do not rely on resolving range hosts by name from your operator box. Use static hosts entries, which the solution guides set up.

Windows workstations

A new workstation (wks) defaults to Windows 11: the canvas seeds windows_11, and a workstation with no os compiles to it. A domain controller or a plain server dropped from the palette, or one with no os, is Windows Server 2022; the SQL Server, Web Server, File Server, and AD CS Server presets start as Windows Server 2019. The shipped blueprints' former Windows 10 workstations are now Windows 11.

What a Windows 10 or 11 host boots depends on the provider:

Provider Windows 11 Windows 10
Azure the windows-11 Marketplace image, SKU win11-26h2-pro the Windows-10 Marketplace image, SKU win10-22h2-pro-g2
GCP, AWS Windows Server 2022 Windows Server 2022

GCP and AWS publish no Windows client image, so a Windows 10 or 11 host there boots Windows Server 2022, and the validator notes it with CAP005 (info). Windows 10 is past end of support: Microsoft ended it on 2025-10-14. The Inspector lists it as "Windows 10 (past end of support)", and a host set to windows_10 on Azure, Proxmox, or ESXi gets the info note CAP006. Neither note blocks an export, and windows_10 stays available for labs that need it.

On a client edition of Windows (Azure, and Proxmox or ESXi with a client image), a user's scheduled tasks start only after someone has signed in at the console since boot. So a host whose user activity bots run as a user (the logon bot, the scheduled task, the stored credential, the poisoning bots) signs that user in at the console at every boot, with the password kept as an LSA secret rather than in the Winlogon registry key. The host reboots once when this is first set, and DEFENSE-BRIEFING.md lists the sign-in for that host. Server editions, and GCP and AWS workstations, which boot Windows Server 2022, are unchanged.

On the roadmap

  • Proxmox and ESXi are on the roadmap and not yet supported. Neither can allocate a public address on its own, so redirector reachability there depends on a network redStackPRO does not control.

AWS quotas and regional planning

AWS quotas are per region, and a compile does not check them against your account. Scope them before you deploy, so an apply does not fail partway and leave partial infrastructure running and billing. Every item below is per region: a new region means re-checking these.

Elastic IPs

The AWS default is 5 Elastic IPs per region (Service Quotas code L-0263D0A3, "EC2-VPC Elastic IPs"). The export allocates one for each host that takes a public address (the jumpbox and, on the attack side, the redirector) and one for each network that builds a NAT gateway.

Range Elastic IPs What takes them
Defense/AD range about 2 jumpbox, NAT gateway
Offense range about 3 jumpbox, redirector, NAT gateway

At the default of 5, a region holds only one or two concurrent ranges. Request an increase per region in advance:

aws service-quotas request-service-quota-increase --service-code ec2 --quota-code L-0263D0A3 --desired-value <n> --region <region>

An EIP shortfall surfaces at provisioning, after the instances are already up, so a failed apply leaves them running. Destroy the partial range explicitly (see Managing a range: status, start, stop, teardown in Deploying a Range) rather than leaving it to bill.

vCPUs

AWS caps running On-Demand instance vCPUs per region under "Running On-Demand Standard (A, C, D, H, I, M, R, T, Z) instances". Hosts are mostly t3.large and t3.medium (2 vCPU each), so a large AD range (for example full GOAD plus a SIEM) can exceed the default. Check the quota and raise it before large deploys.

Kali Marketplace subscription

If a topology includes a Kali operator, the Kali AMI needs a one-time Marketplace subscription on the account. A subscription covers the whole account, every region. redStackPRO generates code and never performs account actions, so you subscribe once yourself.

Key pair name

An EC2 key pair name is region-global (unique per region across the account). The export names the key pair <prefix>-key plus a random suffix per deployment, kept in that deployment's Terraform state (the auto-stop IAM role and schedule get the same suffix), so two ranges in one region never collide on it, even with the same prefix. A distinct prefix per range still keeps host names clear.

GCP quotas and setup

A GCP deploy needs a project with billing enabled, the right API turned on, and enough quota. A compile does not check any of this against your account.

Project and billing

GCP resources live inside a project, and a project needs billing enabled before it will create anything. If you do not already have one:

gcloud projects create <project-id> --organization=<org-id>
gcloud billing projects link <project-id> --billing-account=<billing-account-id>

Or create the project and link a billing account from the console (console.cloud.google.com). Either way, project in deploy.tfvars is this project's id, not its display name or number.

Compute Engine API

The export's GCP module only creates Compute Engine resources (instances, networks, addresses, routers, NAT), so that is the one API to enable:

gcloud services enable compute.googleapis.com --project <project-id>

The export does not touch Cloud DNS or any other GCP API. The redirector's DNS A record is something you create by hand at your own registrar, not a GCP resource. See Deploying a Range.

vCPU quota

GCP caps running Compute Engine vCPUs per project under CPUS_ALL_REGIONS (default 32 per project, not per region). This is the quota that actually bites: a topology with enough hosts can exceed it well before any single-region or machine-type limit does. Check it, and raise it if needed, under IAM & Admin > Quotas in the console, filtered to the Compute Engine API, before a large deploy.

External IP quota

The export reserves a static external address for the jumpbox, and for a redirector on the attack side, so each range holds one or two per region. GCP also caps external IP addresses per region. Check the same Quotas page, filtered to Compute Engine "IP addresses", before running more than a couple of ranges in one region.

Flag: unlike AWS's service-quotas CLI, a GCP quota increase is normally requested through the console UI, not a single scriptable command. Confirm the current process in the console before planning around a CLI-only flow.

Azure quotas and setup

An Azure deploy needs a subscription, the resource providers the export uses, and enough quota. Unlike AWS and GCP, the deploy checks the quota itself before it applies. In short:

  • Subscription. subscription_id in deploy.tfvars. Find it with az account show --query id -o tsv.
  • Resource providers. Microsoft.DevTestLab has to be registered for the auto-stop schedule (every shipped blueprint sets one). The core set (Microsoft.Compute, Microsoft.Network, Microsoft.Storage, Microsoft.ManagedIdentity, and the rest) is registered by Terraform at apply when your identity may register providers.
  • vCPUs. Azure caps vCPUs per region in total and per size family. A new or trial subscription often has only 4 to 10 regional vCPUs and family quotas around 10; the full redstack needs 16.
  • Size restrictions. Some subscriptions are barred from a size or a whole size family in a region (SkuNotAvailable). Override the size per role with vm_sizes in deploy.tfvars.
  • Public IPs. The tested blueprints take 2 (defense) or 3 (offense): the jumpbox, the NAT gateway, and on offense the redirector. Each further redirector or NAT gateway adds one.

The commands, the default size per role, and what the preflight checks are in Cloud Prerequisites.

Exposure

Exposure is a ceiling, not a default. A segment declares how exposed its hosts may be, and the compiler will not emit a host more exposed than its segment allows. If a host asks for a public address in a segment that permits none, the validator raises EXP005 rather than deploying something that reads as exposed and is actually unreachable. See Validation.

Ingress ports by node kind

Every rule that admits traffic from outside the range exists because an edge called for it or because of operator_source_ranges; nothing is open to the internet by default. Inside, an offense stack is open to itself: every host accepts all traffic from the stack's own networks, peered ones included. A defense range stays segmented: domain hosts and the SIEM accept all traffic from their own segment, and everything else is edge derived. Egress is a separate question: the cloud providers leave the security group or firewall open at egress, and what actually leaves is decided by a segment's egress field and its NAT or internet gateway routing, not by a port rule.

Node kind Source Port Protocol Purpose
jumpbox operator_source_ranges 22 tcp operator ssh access
jumpbox operator_source_ranges 443 tcp the Guacamole portal, access_mode: public (default) only
jumpbox operator_source_ranges the vpn_port overlay (default 51820 WireGuard, 1194 OpenVPN) the vpn_protocol overlay (udp or tcp) operator VPN access, access_mode: wireguard or openvpn only; the portal then sits behind this tunnel instead of on 443
jumpbox its own segment all all the foothold rule: accepts traffic range hosts initiate back to it, such as a coerced or relayed NTLM callback, or a pivot return
redirector 0.0.0.0/0 the fronts edge's listen_port (443 in every shipped example) tcp, or udp when the edge's protocol is dns the fronted C2 traffic
redirector 0.0.0.0/0 80 tcp the Certbot ACME http-01 challenge, and the http to https redirect
teamserver the redirector on a fronts edge the edge's upstream_port (443 in every shipped example) tcp, or udp when the edge's protocol is dns fronted C2 traffic forwarded by the redirector
teamserver the operator(s) that drive it Mythic 7443, Sliver 31337, Adaptix 4321 tcp the C2's own operator control plane (a none teamserver opens none; see the note below)
collector senders on a logs_to edge the collector's ingest_port overlay, default 5044 tcp log shipping ingest, Logstash's beats input by default

The jumpbox also reaches every host it manages, on 22 (ssh) or 5986 (WinRM), plus 3389 when the Guacamole portal needs an RDP tile (a Windows host, or a desktop mode Kali operator). Those rules sit on the managed host's own firewall entry, not the jumpbox's, so they are not in the table above.

The none teamserver. A none teamserver stands up no service. It is a plain Debian box for a custom, operator-supplied C2 (OC2, Cobalt Strike, or any C2 you bring), so redStackPRO opens no control port for it.

Clone this wiki locally