Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/BaddKharma/redStack/llms.txt

Use this file to discover all available pages before exploring further.

OpenVPN mode is for closed-network Pro Lab environments — HackTheBox Pro Labs, VulnLab, and Proving Grounds — where target machines cannot reach the public internet and have no public DNS. In this mode the redirector establishes an OpenVPN tunnel to the platform’s VPN endpoint, and all internal lab machines (WIN-OPERATOR, C2 servers) route their traffic to the target network through that tunnel.
This section applies only when enable_external_vpn = true is set in terraform.tfvars. The default redStack deployment uses a public domain, trusted TLS, and htaccess filtering. Only follow this guide if you are targeting an isolated OpenVPN environment.

How it works

AWS VPC peering cannot deliver packets whose destination IP falls outside either VPC’s CIDR. Packets to a target like 10.13.38.33 are silently dropped at the AWS fabric regardless of route tables or security groups. WireGuard solves this by creating an encrypted Layer 3 tunnel between Guacamole and the redirector. Internal machines route ExtVPN-bound traffic to Guacamole’s ENI within the same VPC. Guacamole encapsulates those packets in WireGuard UDP frames addressed to the redirector’s VPC IP (10.60.x.x), which passes VPC peering cleanly. The redirector decapsulates and forwards out tun0 (OpenVPN) to the target network. Traffic path:
[Teamserver / WIN-OPERATOR]
  → default VPC route → Guacamole (wg0 gateway, MASQUERADE onto 10.100.0.2)
  → WireGuard (UDP 51820, via VPC peering)
  → Redirector (wg0 server: 10.100.0.1)
  → tun0 (OpenVPN, MASQUERADE onto VPN-assigned IP)
  → CTF target network
Two NAT hops occur in each direction. ExtVPN targets see traffic from the redirector’s tun0 IP; conntrack reverses both MASQUERADEs on the way back. What Terraform provisions when enable_external_vpn = true:
  • Installs OpenVPN client on the redirector (ext-vpn systemd service)
  • Installs WireGuard on redirector and Guacamole (keys generated on Guacamole at boot — no pre-deployment setup needed)
  • Enables IP forwarding on both instances
  • Disables AWS source_dest_check on both ENIs (required for packet forwarding)
  • Adds VPC route table entries that send each CIDR in external_vpn_cidrs to Guacamole’s ENI
WireGuard addresses:
InstanceInterfaceAddress
Redirectorwg0 (server)10.100.0.1/30
Guacamolewg0 (client)10.100.0.2/30

Step 1: Configure terraform.tfvars

Before deploying, add the following to terraform.tfvars:
enable_external_vpn                  = true
enable_redirector_htaccess_filtering = false
redirector_domain                    = ""   # leave empty; redirector uses its public Elastic IP
external_vpn_cidrs                   = ["10.10.0.0/16"]  # match your CTF platform's target range
enable_redirector_htaccess_filtering = false disables scanner and AV vendor blocking. That filter is not useful in isolated lab environments and would add unnecessary latency. Skip the following steps from the main deployment guide — they do not apply in OpenVPN mode:
  • Step 1.6 (Point Domain to Redirector) — no domain or DNS record is needed
  • Step 3.1 (Obtain SSL Certificate via Certbot) — a self-signed certificate with the redirector’s public Elastic IP as the Subject Alternative Name is generated automatically
Check the target platform’s routing table (ip route show dev tun0 after connecting) to find which CIDRs it pushes. Common ranges are 10.10.0.0/16 (HTB), 10.13.0.0/16 (HTB Pro Labs), and 10.129.0.0/16 (HTB Academy). Add all relevant ranges to external_vpn_cidrs.
If you already deployed without enable_external_vpn = true, you must run terraform destroy followed by a fresh terraform apply. The WireGuard setup runs as cloud-init at first boot and cannot be triggered on a running instance by re-applying Terraform.

Step 2: Deploy and obtain your .ovpn file

1

Deploy the infrastructure

terraform apply
Type yes when prompted. Guacamole automatically configures the WireGuard tunnel with the redirector during cloud-init. Wait approximately 5 minutes for all instances to finish initializing.
2

Download your .ovpn file

Log into your CTF platform and download the VPN configuration file:
  • HackTheBox: Labs → Access → OpenVPN → Download
  • VulnLab: Dashboard → VPN → Download
  • Proving Grounds: Dashboard → Download VPN Pack

Step 3: Transfer the .ovpn file to the redirector

Drop the .ovpn file into ~/vpn/ on the redirector. The ext-vpn service picks up whichever file is present in that directory. If multiple files are present, it uses the first one alphabetically.
1

Open the redirector SSH session

In Guacamole, click Apache Redirector (SSH).
2

Open the sidebar

Press Ctrl+Alt+Shift to open the Guacamole sidebar.
3

Upload the file

Click Devices and select your .ovpn file. It uploads to the home directory (~).
4

Move it into the vpn directory

mv ~/*.ovpn ~/vpn/

Step 4: Start the VPN tunnel

SSH to the redirector from WIN-OPERATOR:
ssh admin@<REDIR_PRIVATE_IP>
Start and verify the VPN service:
sudo systemctl start ext-vpn
sudo systemctl status ext-vpn
The ext-vpn service runs OpenVPN under systemd with --pull-filter ignore "redirect-gateway". This filter is critical — it prevents the VPN from hijacking the redirector’s default route, which would break all VPC peering and C2 proxy connectivity. iptables MASQUERADE rules are applied automatically when tun0 comes up and removed when it goes down. Check real-time VPN logs:
journalctl -u ext-vpn -f
The ext-vpn service will fail to start if no .ovpn file exists in ~/vpn/. Complete Step 3 before running this command.

Step 4b: Get the tun0 IP for C2 callbacks

The OpenVPN server assigns a dynamic IP to tun0 at connect time. In a fully isolated environment where target machines can only reach the VPN network (not the public internet), use this IP as the C2 callback address.
ip addr show tun0
Or extract just the IP:
ip -4 addr show tun0 | grep -oP '(?<=inet\s)\d+(\.\d+)+'
Generate C2 agents after starting ext-vpn. The tun0 IP is only assigned after the VPN connects, and it changes each time you reconnect. Agents with a baked-in tun0 IP stop working after a reconnection that assigns a different IP.
Use HTTP (port 80) for VPN-based callbacks. The self-signed certificate on the redirector only covers the public Elastic IP as a Subject Alternative Name, not the tun0 IP. Traffic between the target and the redirector travels inside the encrypted OpenVPN tunnel, so it is already protected in transit.
FrameworkCallback address
Mythiccallback_host = "http://<tun0-ip>", callback_port = 80
Sliver--http http://<tun0-ip>/cloud/storage/objects/
HavocHosts: <tun0-ip>, PortConn: 80
All other settings (URI prefix, X-Request-ID header) remain the same as in a standard deployment.
If the target machine has outbound internet access (most HTB standalone boxes do), you can use the public Elastic IP with HTTPS instead. The tun0 IP is only required when targets are fully isolated and can only reach the VPN network.

Step 5: Verify connectivity from internal machines

After the VPN tunnel is up, verify that all internal lab machines can reach the target network. Routing is configured at the VPC level — the Windows workstation, all C2 servers, and Guacamole can all reach targets through the tunnel without any additional configuration.
ping <ctf-target-ip>
Or run a more thorough probe:
nmap -sC -sV <ctf-target-ip>

Step 6: Stop the VPN

sudo systemctl stop ext-vpn
This stops the OpenVPN process and removes the iptables MASQUERADE rules on tun0. The .ovpn file is preserved in ~/vpn/ — restart the tunnel any time with sudo systemctl start ext-vpn without re-uploading.

WireGuard status checks

Verify the WireGuard tunnel is healthy at any time. Both peers should show a recent handshake timestamp.
# Should list guacamole as a peer with a recent handshake time
sudo wg show

Important notes

Traffic to other destinations — the public internet, VPC peers, C2 backends — is completely unaffected. Only CIDRs listed in external_vpn_cidrs are sent through the WireGuard/OpenVPN path. Add or modify CIDRs in terraform.tfvars and redeploy if your platform uses different subnets.
The WireGuard service (wg-quick@wg0) is enabled at boot on both the redirector and Guacamole and comes up automatically after a reboot. The OpenVPN tunnel (ext-vpn) does not auto-start. Run sudo systemctl start ext-vpn after each reboot or whenever you want to connect to the target platform.
Guacamole generates both keypairs at boot, writes its own WireGuard config, and SSHes into the redirector to push the server config and start the service. There is nothing to configure before running terraform apply.
AWS disables the source/destination check on both the redirector and Guacamole ENIs when enable_external_vpn = true. This is required for packet forwarding — without it, AWS drops packets whose source or destination IP does not match the interface’s assigned IP.
Agents built with a hardcoded tun0 IP stop working after a VPN reconnection that assigns a different IP. Check ip addr show tun0 after each reconnect and regenerate agents if the IP changed. If targets have internet access, use the stable public Elastic IP with HTTPS to avoid this.
The ext-vpn service runs with --pull-filter ignore "redirect-gateway". This prevents the OpenVPN server from pushing a default route that would overwrite the redirector’s existing default route and break VPC peering and all C2 traffic. Only the specific CIDRs in external_vpn_cidrs are routed through the tunnel.