Repository navigation
17. Troubleshooting
Reference for components misbehaving after deployment. Each section names a specific failure mode with symptoms, root cause, and fix. If you don't find your issue here, check /var/log/user-data.log on the affected instance; it captures the full provisioning output.
All three C2 servers (Mythic, Sliver, Adaptix) have no public IPs. All C2 traffic must flow through the redirector. From the redirector:
ping -c 3 mythic
ping -c 3 sliver
ping -c 3 adaptix| C2 | Where to look |
|---|---|
| Mythic | Active Callbacks page in the web UI |
| Sliver |
sessions command in the Sliver console |
| Adaptix | Active sessions in the Adaptix client |
sudo tail -20 /var/log/apache2/redirector-ssl-access.log
sudo tail -20 /var/log/apache2/redirector-access.logURI prefixes identify which C2 is receiving traffic:
/cdn/media/stream/ = Mythic
/cloud/storage/objects/ = Sliver
/edge/cache/assets/ = Adaptix
Symptoms: The redirector reaches the tunneled target cleanly (ping and TCP probe both succeed from the redirector, tun0 is up, OpenVPN shows Initialization Sequence Completed), but every internal host behind Guacamole (Windows operator, Kali, C2 servers) times out to the same target. It looks like a routing problem but is not.
Cause: A Guacamole rebuild generates fresh WireGuard keys and pushes a new server config to the redirector, but guacamole_setup.sh brings up the redirector side with systemctl start wg-quick@wg0 instead of restart. Because wg0 is already running from the first deploy, start is a no-op, so the redirector keeps the old keys. The new guac keys and the stale redirector keys don't match, the WireGuard handshake fails, and the guac-to-redirector hop goes down while the redirector's own OpenVPN path to the target stays up.
Confirm on the redirector:
sudo wg showIf the Guacamole peer shows no recent handshake and transfer near zero, that's it.
Fix:
sudo systemctl restart wg-quick@wg0
sudo wg showGive it a few seconds for guac's keepalive to produce a fresh handshake, then re-test from the Windows operator (Test-NetConnection <TARGET_IP> -Port 445).
Prevention: Do not rebuild Guacamole mid-session. Deploy and validate the lab before it's needed and leave guac alone. Source fix (start to restart in guacamole_setup.sh) is backlogged.
cd /opt/Mythic
sudo ./mythic-cli statusExpected: eight core containers + apollo + http, all running. The localhost-binding warnings are expected and harmless.
Get admin password:
sudo cat /opt/Mythic/.env | grep MYTHIC_ADMIN_PASSWORDWeb UI from the Windows workstation: https://mythic:7443. Log in as mythic_admin with the password from above.
docker psExpected: three containers all up: guacamole/guacamole, postgres:15, guacamole/guacd.
sudo /home/admin/test_redirector.shChecks Apache status, VirtualHost config, connectivity to all three C2 backends, and header/decoy page behavior.
Check redirect.rules is loaded:
grep -c 'RewriteCond' /etc/apache2/redirect.rulesTest security layers manually (curl's default User-Agent matches scanner patterns and is blocked by redirect.rules — the block below spoofs a browser UA and is the correct test method):
UA="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
HEADER_VALUE="<token from deployment_info.txt>"
TARGET="yourdomain.tld" # or <REDIR_PUBLIC_IP> for IP-only/Tunneled Access
# Should return decoy page (no header)
curl -sk -A "$UA" https://$TARGET/
# Should return decoy page (wrong header)
curl -sk -A "$UA" -H "X-Request-ID: wrong-value" https://$TARGET/cdn/media/stream/test
# Should proxy to Mythic (connection refused if no listener, expected)
curl -sk -A "$UA" -H "X-Request-ID: $HEADER_VALUE" https://$TARGET/cdn/media/stream/testwhich sliver-serverIf missing, see Sliver > Troubleshooting.
sudo systemctl status adaptixIf not running: sudo systemctl start adaptix. If the binary is missing, the build did not finish; run ~/build_adaptix_server.sh and see Adaptix > Troubleshooting.
Each Guacamole SSH connection should connect without a password prompt and land at the correct hostname:
Mythic (SSH) > admin@mythic:~$
Guacamole (SSH) > admin@guac:~$
Redirector (SSH) > admin@redirector:~$
Sliver (SSH) > admin@sliver:~$
Adaptix (SSH) > admin@adaptix:~$
Kali (SSH) > admin@kali:~$
SSH access model: All lab hosts are accessed via the Guacamole portal (SSH connections) or MobaXterm pre-configured sessions on the Windows operator workstation. The redirector accepts only ports 80 and 443 publicly. Guacamole has a break-glass direct SSH rule for localPub_ip (key-based, advanced users only) if the portal itself is unavailable.
Warning
Do not destroy individual components with targeted terraform destroy -target on the redirector alone. (terraform taint was removed in Terraform 1.0; redStack requires ≥ 1.0, so it is unavailable. The modern equivalent is terraform apply -replace=<resource>, which carries the same state risk.) Partial destroys can corrupt Terraform state and leave orphaned AWS resources (dangling ENIs, stale security group rules, broken VPC peering). If the redirector is in a broken state that cannot be recovered by restarting Apache or re-running setup scripts, the supported recovery path is a full terraform destroy && terraform apply.
Note
AWS and Azure cloud IP blocks are commented out by default in redirect.rules because this lab runs in AWS. If you deploy outside cloud environments you can re-enable them by editing /etc/apache2/redirect.rules and uncommenting the relevant blocks, then sudo systemctl reload apache2.
Symptoms: Agent executes but no callback in Mythic / Sliver / Adaptix.
Checklist:
- Listener is running on the C2 server
- Callback Host and Port match the redirector's domain/IP and port 443
- Agent sends the correct
X-Request-IDheader with the auto-generated token - Agent URI uses the correct prefix (
/cdn/media/stream/,/cloud/storage/objects/, or/edge/cache/assets/) - Redirector Apache is running with all VirtualHosts enabled
- Redirector can reach the C2 server's private IP (
ping mythic) - Agent user-agent isn't blocked by
redirect.rules(no scanner/AV strings)
Debug on the redirector:
sudo apache2ctl -S
systemctl status apache2
# Logs (differentiate by URI prefix)
sudo tail -100 /var/log/apache2/redirector-ssl-access.log
sudo tail -100 /var/log/apache2/redirector-ssl-error.log
# Pre-installed end-to-end test
sudo /home/admin/test_redirector.shError: Invalid value for input variable
on terraform.tfvars line 11:
11: localPub_ip = ["203.0.113.5/32", "198.51.100.42/32"]
The given value is not suitable for var.localPub_ip declared at
variables.tf:15,1-23: string required, but have tuple.
Cause: your clone predates the change that made localPub_ip a list(string). The
tfvars supplies a bracketed list, but variables.tf in that checkout still declares a
single string, so Terraform rejects the value before it reaches any resource. terraform init succeeding does not clear this; the type check happens at plan time.
Fix: update the repo, then re-plan.
cd redStack
git pull
cd terraform
terraform planKeep the list form in terraform.tfvars; it is correct on current main. If you cannot
pull yet, the one-line workaround is to collapse the value back to a single string
(localPub_ip = "203.0.113.5/32"), which allowlists only that one address.
Cause: AWS Marketplace EULA for the Kali Linux AMI hasn't been accepted on this account.
Fix: Visit https://aws.amazon.com/marketplace/pp/prodview-fznsw3f7mq7to, click Continue to Subscribe, then Accept Terms. Re-run terraform apply; no state cleanup needed. See Prerequisites > Step 5.
# List available keys
aws ec2 describe-key-pairs --query 'KeyPairs[].KeyName'
# Update terraform.tfvars with correct nameAWS accounts have a default limit of five VPCs per region. redStack creates two (team server + redirector), so you need at least two free slots.
If at the limit, either delete unused VPCs or switch to the existing default VPC: in terraform.tfvars, set use_default_vpc = true.
The Kali Linux AMI is the only AWS Marketplace dependency in redStack. All other AMIs (Redirector, Mythic, Sliver, Adaptix, Guacamole, Windows) are standard Amazon-published AMIs with no Marketplace gate. If you hit OptInRequired for any non-Kali host, check that terraform.tfvars is not pointing at a custom AMI ID.
← Previous: Cost Management | Next: redStack on GitHub →
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it."
Brian Kernighan, The Elements of Programming Style (1978)