# How to Configure and Set Up CAPEv2's Interactive Desktop Feature Utilizing Guacamole

> Learn to configure and set up CAPEv2's interactive desktop with Guacamole. Stream live VNC/RDP sessions directly to your browser for enhanced malware analysis.

- Repository: [Kevin O'Reilly/capev2](https://github.com/kevoreilly/capev2)
- Tags: how-to-guide
- Published: 2026-03-05

---

**CAPEv2 streams live VNC or RDP sessions from analysis VMs to your browser via Apache Guacamole by enabling the `[guacamole]` section in [`conf/web.conf`](https://github.com/kevoreilly/capev2/blob/main/conf/web.conf), installing the `guacd` daemon and `guac-web` container, and submitting tasks with the `interactive=1` flag.**

CAPEv2's interactive desktop feature allows malware analysts to remotely control analysis virtual machines directly from their web browser using Apache Guacamole. This guide explains how to configure and set up CAPEv2's interactive desktop feature utilizing Guacamole based on the official source code in the `kevoreilly/capev2` repository.

## How CAPEv2 Interactive Desktop Works

CAPEv2 leverages a dedicated Django application to proxy WebSocket connections between the analyst's browser and the Guacamole daemon (`guacd`). When you submit a sample with the interactive flag enabled, the system stores `interactive_desktop: true` in the task JSON, which [`web/submission/views.py`](https://github.com/kevoreilly/capev2/blob/main/web/submission/views.py) processes to trigger the Guacamole workflow.

The architecture relies on three core components:
- **Guacamole client library** (`guacamole.client.GuacamoleClient`) in [`web/guac/consumers.py`](https://github.com/kevoreilly/capev2/blob/main/web/guac/consumers.py) handles the binary Guacamole protocol over TCP to `guacd`
- **WebSocket consumer** (`GuacConsumer`) in the same file forwards browser data to `guacd` and manages session recordings
- **Django view** (`guac.views.index`) in [`web/guac/views.py`](https://github.com/kevoreilly/capev2/blob/main/web/guac/views.py) generates signed, base64-encoded session tokens containing the task ID, Guacamole label, and guest IP

## Prerequisites and Architecture Overview

Before configuring the interactive desktop, ensure your CAPEv2 instance meets these requirements:

| Component | Source File | Purpose |
|-----------|-------------|---------|
| **Guacamole client** | [`web/guac/consumers.py`](https://github.com/kevoreilly/capev2/blob/main/web/guac/consumers.py) | Binary protocol handler for `guacd` |
| **WebSocket consumer** | [`web/guac/consumers.py`](https://github.com/kevoreilly/capev2/blob/main/web/guac/consumers.py) | Browser-to-guacd proxy and recording writer |
| **Session generator** | [`web/guac/views.py`](https://github.com/kevoreilly/capev2/blob/main/web/guac/views.py) | Creates signed tokens (`guac.views.index`) |
| **URL routing** | [`web/guac/urls.py`](https://github.com/kevoreilly/capev2/blob/main/web/guac/urls.py) | Maps `/guac/` paths and WebSocket endpoints |
| **Settings module** | [`web/guac_settings.py`](https://github.com/kevoreilly/capev2/blob/main/web/guac_settings.py) | Django config for Guacamole mode |
| **Submission logic** | [`web/submission/views.py`](https://github.com/kevoreilly/capev2/blob/main/web/submission/views.py) | Sets `interactive_desktop` flag in task JSON |
| **Startup routine** | [`lib/cuckoo/core/startup.py`](https://github.com/kevoreilly/capev2/blob/main/lib/cuckoo/core/startup.py) | Creates `storage/guacrecordings` directory |
| **Configuration** | [`conf/web.conf`](https://github.com/kevoreilly/capev2/blob/main/conf/web.conf) | Connection parameters and feature toggles |

You must use KVM/QEMU as your machinery backend, as CAPEv2's interactive desktop requires VNC access to the guest VMs.

## Step-by-Step Configuration Guide

### Install Guacamole Services

CAPEv2 provides an automated installer script that deploys the required Docker containers and systemd services. Run the following command as root:

```bash
sudo ./installer/cape2.sh guacamole

```

This installs:
- `guacd` (the Guacamole proxy daemon) as a systemd service
- `guac-web` container (the HTML5 client) listening on port 8080
- Systemd units: `guacd.service` and `guac-web.service`

### Enable Guacamole in CAPEv2 Configuration

Edit [`conf/web.conf`](https://github.com/kevoreilly/capev2/blob/main/conf/web.conf) (or copy from `conf/default/web.conf.default` if the file does not exist) and configure the `[guacamole]` section:

```ini
[guacamole]
enabled = yes
mode = vnc                 # Options: vnc, rdp

username = <optional>
password = <optional>
guacd_host = localhost
guacd_port = 4822
vnc_host = 127.0.0.1      # IP of the host running the VMs

guest_protocol = vnc
guest_width = 1280
guest_height = 1024

```

The `mode` parameter determines whether CAPEv2 connects to the guest via VNC or RDP. For KVM/QEMU deployments, `vnc` is the standard protocol.

### Configure the Web Front-End

The Guacamole UI is served under the `/guac/` URL prefix. You must proxy WebSocket connections to the `guac-web` service (port 8080 by default).

Add this location block to your NGINX configuration:

```nginx
location /guac/ {
    proxy_pass http://127.0.0.1:8080/;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
}

```

After editing, reload NGINX:

```bash
sudo systemctl reload nginx

```

### Enable VNC on Analysis VMs

CAPEv2's interactive desktop requires VNC access to the guest. Ensure your VM XML configuration includes a graphics device:

```xml
<graphics type='vnc' port='-1' listen='0.0.0.0'/>

```

The `port='-1'` tells QEMU to auto-allocate a port. The VM must be reachable from the host defined in `vnc_host` (typically the CAPEv2 host IP).

### Restart Services and Verify

After completing configuration, restart all related services:

```bash
sudo systemctl restart cape-web guacd.service guac-web.service

```

Verify that `guacd` is listening on port 4822:

```bash
sudo ss -tlnp | grep 4822

```

Check that the recordings directory exists (created by [`lib/cuckoo/core/startup.py`](https://github.com/kevoreilly/capev2/blob/main/lib/cuckoo/core/startup.py)):

```bash
ls -la /opt/CAPEv2/storage/guacrecordings/

```

## Using the Interactive Desktop

### Submitting Samples via Web UI

To launch an interactive session, submit a sample through the CAPEv2 web interface and tick the **Interactive Desktop** checkbox. This sets `interactive_desktop: true` in the task JSON, which [`web/submission/views.py`](https://github.com/kevoreilly/capev2/blob/main/web/submission/views.py) processes to trigger the Guacamole workflow.

### Submitting via REST API

For automated submissions, include the `interactive=1` parameter:

```bash
curl -X POST "https://<cape-host>/api/v1/tasks/create" \
     -H "Authorization: Bearer <API_KEY>" \
     -F "file=@/tmp/malware.exe" \
     -F "interactive=1"

```

The backend checks `web_conf.guacamole.enabled` before marking the task for interactive access.

### Generating Session Tokens Manually

If you need to construct a Guacamole URL manually, generate a signed session token using the same logic found in [`web/guac/views.py`](https://github.com/kevoreilly/capev2/blob/main/web/guac/views.py):

```python
from uuid import uuid3, NAMESPACE_DNS
from base64 import urlsafe_b64encode as ub64enc

sid = uuid3(NAMESPACE_DNS, "0000").hex[:16]           # Random session ID

ip = "192.168.2.2"                                   # Guest IP address

vm_name = "win10"                                   # Label from web.conf labels_and_ports

session_data = ub64enc(f"{sid}|{vm_name}|{ip}".encode()).decode()
print(session_data)   # Append to /guac/<task_id>/ in your browser

```

This base64-encoded string contains the session ID, VM label, and guest IP required by the `GuacConsumer` in [`web/guac/consumers.py`](https://github.com/kevoreilly/capev2/blob/main/web/guac/consumers.py).

## Troubleshooting Common Issues

### Connection Refused Errors

If the browser cannot connect to the interactive desktop, verify that the `guacd` daemon is running and accessible on the configured port (default 4822). Check the service status with `sudo systemctl status guacd`, review the log file at `/opt/CAPEv2/web/guac-server.log`, and ensure `guacd_host` and `guacd_port` in [`conf/web.conf`](https://github.com/kevoreilly/capev2/blob/main/conf/web.conf) match your deployment. Also verify that firewall rules allow TCP traffic on port 4822 between the CAPEv2 web application and the Guacamole daemon.

### WebSocket Upgrade Failures

The NGINX configuration must properly handle WebSocket upgrades for the `/guac/` path. If you see 400 Bad Request errors or connection drops, confirm that `proxy_set_header Upgrade $http_upgrade` and `proxy_set_header Connection "upgrade"` are present in your NGINX location block, and that `proxy_http_version 1.1` is specified.

### ALLOWED_HOSTS Errors

If Django returns 400 Bad Request with "Invalid HTTP_HOST header", edit [`web/web/settings.py`](https://github.com/kevoreilly/capev2/blob/main/web/web/settings.py) and add your CAPEv2 hostname to the `ALLOWED_HOSTS` list. This is required when accessing the interactive desktop through a reverse proxy or load balancer.

### VNC Connectivity Issues

Verify that the analysis VM has a VNC server configured in its XML definition with `<graphics type='vnc' port='-1' listen='0.0.0.0'/>`. The VM must be reachable from the host defined in `vnc_host` in [`conf/web.conf`](https://github.com/kevoreilly/capev2/blob/main/conf/web.conf). Check network connectivity and firewall rules between the CAPEv2 host and the VM host if they are separate machines.

## Summary

- **CAPEv2's interactive desktop** uses Apache Guacamole to stream VNC/RDP sessions from analysis VMs to the browser via WebSocket proxies implemented in [`web/guac/consumers.py`](https://github.com/kevoreilly/capev2/blob/main/web/guac/consumers.py).
- **Configuration** requires enabling `[guacamole]` in [`conf/web.conf`](https://github.com/kevoreilly/capev2/blob/main/conf/web.conf), setting `enabled = yes`, and defining connection parameters like `guacd_host`, `vnc_host`, and `mode`.
- **Installation** is automated via `sudo ./installer/cape2.sh guacamole`, which creates systemd services for `guacd` and `guac-web`.
- **Usage** involves submitting samples with `interactive=1` via the web UI or REST API, which triggers the session token generation logic in [`web/guac/views.py`](https://github.com/kevoreilly/capev2/blob/main/web/guac/views.py).

## Frequently Asked Questions

### What is the difference between VNC and RDP modes in CAPEv2's Guacamole integration?

**VNC** (Virtual Network Computing) is the default protocol for KVM/QEMU-based analysis machines and provides framebuffer-level access to the guest desktop. **RDP** (Remote Desktop Protocol) is an alternative that offers better performance on Windows guests but requires the VM to have an RDP server enabled. Configure the mode in [`conf/web.conf`](https://github.com/kevoreilly/capev2/blob/main/conf/web.conf) under the `[guacamole]` section with `mode = vnc` or `mode = rdp`.

### How do I manually generate a Guacamole session URL for debugging?

You can construct a session token using Python to mimic the logic found in [`web/guac/views.py`](https://github.com/kevoreilly/capev2/blob/main/web/guac/views.py). Import `uuid3` from the `uuid` module and `urlsafe_b64encode` from `base64`, then encode a string containing a random session ID, the VM label from your [`web.conf`](https://github.com/kevoreilly/capev2/blob/main/web.conf), and the guest IP address. Append this base64 string to `https://<cape-host>/guac/<task-id>/` to access the desktop directly.

### Why does my browser show "Connection refused" when trying to open an interactive session?

This error typically indicates that the `guacd` daemon is not running or is unreachable on the configured port (default 4822). Verify the service status with `sudo systemctl status guacd`, check the log file at `/opt/CAPEv2/web/guac-server.log`, and ensure `guacd_host` and `guacd_port` in [`conf/web.conf`](https://github.com/kevoreilly/capev2/blob/main/conf/web.conf) match your deployment. Also confirm that firewall rules allow TCP traffic on port 4822 between the CAPEv2 web application and the Guacamole daemon.

### Can I record interactive desktop sessions for later review?

Yes, CAPEv2 automatically records interactive desktop sessions when the feature is enabled. The `GuacConsumer` class in [`web/guac/consumers.py`](https://github.com/kevoreilly/capev2/blob/main/web/guac/consumers.py) writes session recordings to the `storage/guacrecordings` directory, which is created during startup by [`lib/cuckoo/core/startup.py`](https://github.com/kevoreilly/capev2/blob/main/lib/cuckoo/core/startup.py). These recordings capture the entire user interaction with the guest VM and can be replayed through the Guacamole interface or accessed directly from the storage path for forensic analysis.