Reverse Proxy Security
Kasm WebApp roles servers come with an NGINX container (kasm_proxy) that sits in front of service containers and other components within the system. This is a required component, however, organizations may wish to either harden the nginx configuration or place the Kasm Workspaces application behind an Enterprise grade reverse proxy or load balancer.
F5 BIG-IP
By deploying F5 BIG-IP in front of Kasm Workspaces, organizations can leverage Advanced Web Application Firewall (AWAF) capabilities, DDoS protection, and Zero Trust Access Controls to safeguard virtual workspace environments against modern cyber threats. BIG-IP’s iRules and SSL/TLS Offloading provide enterprises with granular control over traffic flows while reducing the processing burden on backend Kasm servers, resulting in both improved security posture and optimized resource utilization.
Seamless Authentication and Secure Access Management
BIG-IP integrates seamlessly with enterprise authentication solutions such as SAML, OAuth, and LDAP, ensuring that access to Kasm Workspaces aligns with corporate identity and access management (IAM) policies. With BIG-IP Access Policy Manager (APM), organizations can enforce conditional access policies based on device posture, user location, and risk scores, preventing unauthorized access and mitigating insider threats. By acting as a centralized authentication gateway, BIG-IP enables Multi-Factor Authentication (MFA) enforcement without modifying Kasm’s internal authentication mechanisms, enhancing security without disrupting user experience.
Traffic Optimization and Performance Enhancements
Enterprises leveraging Kasm Workspaces at scale need a high-performance, low-latency connection experience for remote users. BIG-IP’s intelligent load balancing ensures traffic is distributed efficiently across multiple Kasm Workspace nodes, preventing bottlenecks and ensuring high availability (HA). Features like TCP optimization, HTTP/2 support, and advanced caching minimize \latency while improving the responsiveness of virtualized desktops and applications. With built-in Global Server Load Balancing (GSLB), BIG-IP can also facilitate geo-distributed Kasm deployments, dynamically directing users to the nearest or healthiest data center based on real-time availability.
Enterprise-Grade Threat Intelligence and Compliance
For organizations operating in regulated industries, compliance with security standards such as NIST, ISO 27001, HIPAA, and GDPR is critical. F5 BIG-IP provides automated threat intelligence, real-time bot mitigation, and traffic anomaly detection, ensuring that Kasm Workspaces are protected from credential stuffing, malware injection, and brute force attacks. Enterprises can configure custom security policies to enforce compliance mandates while benefiting from detailed logging, analytics, and SIEM integration to maintain full visibility into workspace access and usage.
Configuring F5 BIG-IP
The following video walks through the deployment of Kasm Workspaces behind a F5 BIG-IP using FAST Templates. This F5 Guide steps through configuring your BIG-IP to server as a reverse proxy.
NGINX
The default configuration of the Kasm NGINX service is fairly well secured, however, there are certain configurations that we cannot harden out of the box because the hardening may break certain use cases and/or degrade compatibility. Organizations that choose to directly expose Kasm Worksapces without placing it behind an Enterprise grade layer 7 security appliance may wish to harden the Kasm NGINX configuration. This guide walks through some of the settings that you may run into with different hardening guides or benchmark frameworks that exist. This is not an all encompassing list, as there is a lot of guidance out there from a number of different sources. We focus on US DoD STIG benchmarks that are released by DISA.
X-Frame-Options Header
Including the X-Frame-Options header
will allow you to block other sites embedding your deployment of Kasm in an iframe within another site. This is
not configured by default in Kasm, because many clients wish to embed Kasm in their own website. The following
example will configure NGINX to add the X-Frame-Options header to same origin, which will require the parent page
to be on the same domain. See the link above for more details on other configurations, such specifying explicit
domain names to be allowed for the parent site. Add this line to each NGINX configuration file that
currently defines add_header
directives in this directory and subdirectories within /opt/kasm/current/conf/nginx.
add_header X-Frame-Options SAMEORIGIN always;
After making modifications, restart the kasm_proxy container.
sudo docker restart kasm_proxy
Content Security Policy
Admins may desire to define a Content Security Policy. The
following header is commented out in /opt/kasm/current/conf/nginx/services.d/website.conf
and in two locations in
/opt/kasm/current/conf/nginx/services.d/upstream_proxy.conf
, remove the proceeding #
before the add_header statement
in all three locations.
add_header 'Content-Security-Policy' "default-src 'unsafe-inline' 'unsafe-eval' 'self' blob: data:;";
You also need to uncomment the following line, there is only one in /opt/kasm/current/conf/nginx/services.d/upstream_proxy.conf
.
proxy_hide_header 'Content-Security-Policy'
After uncommenting the total of 4 lines in the two nginx configuration files, restart the kasm_proxy container.
sudo docker restart kasm_proxy
Cross Origin Embedder Policy
Admins may desire to define a Cross Origin Embedder Policy. The
following header is commented out in /opt/kasm/current/conf/nginx/services.d/website.conf
and in two locations in
/opt/kasm/current/conf/nginx/services.d/upstream_proxy.conf
, remove the proceeding #
before the add_header statement
in all three locations.
add_header 'Cross-Origin-Embedder-Policy' 'require-corp';
You also need to uncomment the following line, there is only one in /opt/kasm/current/conf/nginx/services.d/upstream_proxy.conf
.
proxy_hide_header 'Cross-Origin-Embedder-Policy';
After uncommenting the total of 4 lines in the two nginx configuration files, restart the kasm_proxy container.
sudo docker restart kasm_proxy
TLS Settings
Kasm ships with a default cipher suite and SSL settings that meet a high degree of security compliance out of the
box, however, organizations may wish to define more restrictive SSL cipher suites. The cipher suites are
defined on each WebApp server in the file /opt/kasm/current/conf/nginx/orchestration.conf
.
Kasm’s default SSL Configuration:
ssl_certificate /etc/ssl/certs/kasm_nginx.crt;
ssl_certificate_key /etc/ssl/private/kasm_nginx.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
ssl_stapling on;
ssl_stapling_verify on;
Here is an example of a more secure configuration. Warning: More restrictive cipher suites may break compatibility with older clients.
ssl_protocols TLSv1.3 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ecdh_curve secp521r1:secp384r1;
ssl_ciphers EECDH+AESGCM:EECDH+AES256;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_session_cache shared:TLS:2m;
ssl_buffer_size 4k;
ssl_stapling on;
ssl_stapling_verify on;
In order to configure ssl_dhparam
you will need to generate the dhparam.pem file referenced in the above configuration.
sudo openssl dhparam -out /opt/kasm/current/certs/dhparam.pem 4096
sudo chown kasm:kasm /opt/kasm/current/certs/dhparam.pem
Next, edit the /opt/kasm/current/docker/docker-compose.yaml
file to map in the dhparam.pem file into the nginx
configuration. The following snippet shows only the relevant portions of the yaml configuration. Add the volume
mapping shown on the last line of the below snippet to the proxy definition in the yaml file.
proxy:
container_name: kasm_proxy
image: "kasmweb/nginx:1.25.1"
volumes:
- /opt/kasm/current/certs/dhparam.pem:/etc/ssl/certs/dhparam.pem
Next remove the kasm_proxy container and start kasm services back up.
sudo docker rm -f kasm_proxy
sudo /opt/kasm/bin/start
SSL Certificates
Kasm uses self-signed certificates that are generated during the installation process. The cert and key are stored
on each host at /opt/kasm/current/certs/kasm_nginx.crt
and /opt/kasm/current/certs/kasm_nginx.key
respectively.
Clients may wish to replace these certs with properly signed public SSL certs or certs generated by their organizations
certificate authority. You can replace the cert and key mentioned above with files named the same as those above, in
the PEM format. Ensure both files are owned by the kasm
user.
cd /opt/kasm/current/certs
mv kasm_nginx.crt kasm_nginx.crt.bak
mv kasm_nginx.key kasm_nginx.key.bak
cp /my/cert/location/mycert.pem ./kasm_nginx.crt
cp /my/key/location/mykey.pem ./kasm_nginx.key
chown kasm:kasm /opt/kasm/current/certs/kasm_nginx.crt
chown kasm:kasm /opt/kasm/current/certs/kasm_nginx.key
Next restart the services.
sudo /opt/kasm/bin/stop
sudo /opt/kasm/bin/start
Referrer Policy
You may wish to define a referrer policy which will
keep client browsers from passing the referrer header to external sites. Add this line to each NGINX configuration file that
currently defines add_header
directives in /opt/kasm/current/conf/nginx/services.d/.
add_header Referrer-Policy 'same-origin';
Rate Limiting
Many organizations will require rate limiting. NGINX supports rate limiting of requests, see the NGINX documentation for full details. Kasm Workspaces does not ship with rate limiting enabled, mostly due to the fact that some context of the deployment is needed to configure it properly. First, you need to know if Kasm’s WebApp servers are directly accessible via clients, or if there is a load balancer of some other device between the clients and the web app servers. If there is a device between the client and the Kasm WebApp servers, NGINX may not see the original source IP address of the client, this must be considered when considering which rate limiting approach to take.
If clients access the Kasm WebApp servers directly, then you can create a simple rate limiting policy that imposes
a request rate limit per client based on the source IP address of the client. The following configuration would
be placed above the server
directive within the file /opt/kasm/current/conf/nginx/orchestration.conf
.
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=100r/s;
server {
}
If there is a reverse proxy or load balancer in front of the Kasm WebApp servers, you may want to place the rate limiting on the front facing load balancer instead. NGINX can, however, use the X-Forwarded-For header for rate limiting, assuming the front facing reverse proxy/load-balancer injects this header on proxied requests.
limit_req_zone $http_x_forwarded_for zone=zone:10m rate=100r/s;
After implementing one of the two lines above, you must apply it to each proxied location. Within each .conf
file
located at /opt/kasm/current/conf/nginx/services.d/
, place the following line under each location stanza.
location / {
limit_req zone=mylimit burst=20 nodelay;
}
CORS Headers
Kasm implements proper CORS headers, however, we must use a dynamic origin value. This is considered a low severity
security finding. The following is the offending line, which can be found in multiple files under
/opt/kasm/current/conf/nginx/services.d/
add_header 'Access-Control-Allow-Origin' $http_origin always;
Replace the above line with the following, replace example.com
with your domain name.
add_header 'Access-Control-Allow-Origin' 'https://example.com' always;
This may affect deployments that use sub domains for different Zones. The following more complex example may be used if you must clear this vulnerability and also support multiple domain names with CORs. This uses a dynamic Access-Control-Allow-Origin header value, but whitelists it to a list of regular expressions.
map $http_origin $allow_origin {
~^https?://(.*\.)?example.com(:\d+)?$ $http_origin;
~^https?://(.*\.)?example2.com(:\d+)?$ $http_origin;
default "";
}
location / {
add_header 'Access-Control-Allow-Origin' $allow_origin always;
}