|
|
|

|
|
|
|
|
|
|
|
**English** | [Bahasa Indonesia](home)
|
|
|
|
|
|
|
|
# Slash
|
|
|
|
|
|
|
|
**Rust web server and reverse proxy. HTTP/3 and HTTPS out of the box.**
|
|
|
|
|
|
|
|
Slash brings a web server, reverse proxy, load balancer, TCP/UDP proxy and web application
|
|
|
|
firewall together in one small binary written in Rust. Its configuration is a single file
|
|
|
|
that reads like plain sentences. Prefer clicking to typing? **SPMPlus** gives you a web
|
|
|
|
panel that manages it.
|
|
|
|
|
|
|
|
| <img src="https://kubeman.unej.ac.id/geohot/slash/-/raw/main/brand/slash-logo-fix.png" alt="Slash" width="220"> | <img src="https://kubeman.unej.ac.id/geohot/slash/-/raw/main/brand/logo-spmplus-fix-with-text.png" alt="SPMPlus" width="220"> |
|
|
|
|
|:---:|:---:|
|
|
|
|
| **Slash**: web server + reverse proxy | **SPMPlus**: reverse proxy manager |
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## Four sites, one file
|
|
|
|
|
|
|
|
```
|
|
|
|
email admin@example.com
|
|
|
|
|
|
|
|
example.com, www.example.com proxy localhost:3000
|
|
|
|
blog.example.com wordpress /var/www/blog
|
|
|
|
api.example.com laravel /var/www/api
|
|
|
|
docs.example.com files /srv/docs
|
|
|
|
```
|
|
|
|
|
|
|
|
That is the whole configuration. Let's Encrypt certificates issue themselves, HTTP
|
|
|
|
redirects to HTTPS, HTTP/3 is on, security headers are in place, and PHP runs through
|
|
|
|
php-fpm with safe rules for WordPress and Laravel. `slash check` validates the file before
|
|
|
|
it goes live, with line numbers and suggestions for typos.
|
|
|
|
|
|
|
|
```
|
|
|
|
# Caddyfile # Slashfile
|
|
|
|
blog.example.com { blog.example.com wordpress /var/www/blog
|
|
|
|
root * /var/www/blog
|
|
|
|
php_fastcgi localhost:9000
|
|
|
|
file_server
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## Why Slash
|
|
|
|
|
|
|
|
### Secure from the first line
|
|
|
|
|
|
|
|
- **Memory safe.** Written in Rust with no `unsafe` in Slash's own code. Buffer overflows
|
|
|
|
and use-after-free, the bug classes that have long haunted C web servers, are closed off
|
|
|
|
by design.
|
|
|
|
- **Modern TLS** with rustls and aws-lc: TLS 1.3 by default, post-quantum hybrid key
|
|
|
|
exchange, certificates rotated without a restart.
|
|
|
|
- **Security headers on by default** for every site: CSP, X-Frame-Options,
|
|
|
|
Referrer-Policy, Permissions-Policy, HSTS. Headers that reveal server versions are
|
|
|
|
stripped.
|
|
|
|
- **Secrets encrypted at rest**; the panel uses argon2id, TOTP and passkeys.
|
|
|
|
|
|
|
|
### AssaultCuirass: the built-in WAF
|
|
|
|
|
|
|
|
*Heavy-Duty, Memory-Safe Web Application Firewall Powered by Rust.*
|
|
|
|
|
|
|
|
AssaultCuirass runs the OWASP Core Rule Set v4, the same industry standard used by
|
|
|
|
ModSecurity and Coraza, on an engine written for Slash.
|
|
|
|
|
|
|
|
- **ReDoS-proof.** Regexes run in linear time, so a payload of any length is inspected at
|
|
|
|
a predictable cost.
|
|
|
|
- **Request bodies inspected:** forms, JSON, multipart and XML. XXE attacks are stopped
|
|
|
|
before they reach the application.
|
|
|
|
- **One line to turn it on:**
|
|
|
|
|
|
|
|
```
|
|
|
|
shop.example.com proxy localhost:3000
|
|
|
|
waf block
|
|
|
|
```
|
|
|
|
|
|
|
|
- **Detect mode** to watch traffic first, then **block** when you are confident.
|
|
|
|
Exclusions can be as narrow as a single parameter: `waf skip 942430 ARGS:search`.
|
|
|
|
|
|
|
|
Measured with about 37,000 payloads from
|
|
|
|
[WAF-Payload-Collection](https://github.com/mgm-sp/WAF-Payload-Collection):
|
|
|
|
|
|
|
|
| Attack category | Stopped (paranoia 2) |
|
|
|
|
|---|---|
|
|
|
|
| XSS (20,944 payloads) | 100% |
|
|
|
|
| Log4Shell, Shellshock, XXE | 100% |
|
|
|
|
| Command injection | 98.5% |
|
|
|
|
| SQL injection | 97.2% |
|
|
|
|
| **Total** | **94.8%** |
|
|
|
|
|
|
|
|
About 0.13 ms per request at paranoia 1, paid only by routes that use the WAF.
|
|
|
|
|
|
|
|
### Fast and lean
|
|
|
|
|
|
|
|
Measured on a single i5-10600 PC that also ran the load generator and a dummy upstream:
|
|
|
|
|
|
|
|
| | Result |
|
|
|
|
|---|---|
|
|
|
|
| HTTP/1.1, 1,000 connections | **92,169 req/s**, 0 errors |
|
|
|
|
| HTTPS, 1,000 connections | **81,501 req/s**, 0 errors |
|
|
|
|
| HTTP/3 (QUIC), 1,000 connections | **52,517 req/s**, 0 errors |
|
|
|
|
| 10,000 concurrent users | 9,704 req/s, p50 1.18 ms, 0 errors |
|
|
|
|
| Idle memory | about 28 MB |
|
|
|
|
| Memory per HTTP/2 connection | about 60 KB |
|
|
|
|
|
|
|
|
A static binary of about 15 MB with no system dependencies. Runs on x86_64 and ARM64,
|
|
|
|
down to a VM with 1 vCPU and 512 MB of RAM.
|
|
|
|
|
|
|
|
### Reloads without drama
|
|
|
|
|
|
|
|
A new configuration is fully validated, then swapped in atomically. Open connections keep
|
|
|
|
going, and a faulty configuration is refused before it touches traffic. Slash also keeps
|
|
|
|
the last good configuration, so it carries on serving even while the panel is stopped.
|
|
|
|
|
|
|
|
### More than a web server
|
|
|
|
|
|
|
|
- **PHP** over FastCGI with `wordpress` and `laravel` presets: only real `.php` files run,
|
|
|
|
`wp-content/uploads` stays inert, Laravel's `.env` stays out of reach.
|
|
|
|
- **Reverse proxy** for HTTP/1.1, HTTP/2, HTTP/3, WebSocket and gRPC, with load balancing
|
|
|
|
and active and passive health checks.
|
|
|
|
- **TCP and UDP proxying** for databases, SSH, MQTT, DNS, game servers and WireGuard.
|
|
|
|
- **TLS passthrough by SNI** on port 443, side by side with regular HTTPS sites.
|
|
|
|
- **Static files** with SPA support and pre-compressed files, plus zstd, Brotli and gzip
|
|
|
|
compression.
|
|
|
|
- **Rate limiting, access lists and micro-cache** per route.
|
|
|
|
|
|
|
|
```
|
|
|
|
tcp :5432 proxy 10.0.0.5:5432 10.0.0.6:5432
|
|
|
|
allow 10.0.0.0/8
|
|
|
|
udp :51820 proxy 10.0.0.3:51820
|
|
|
|
mail.example.com passthrough 10.0.0.7:443
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## Slash among popular web servers
|
|
|
|
|
|
|
|
| | **Slash** | Caddy | Nginx | Apache httpd |
|
|
|
|
|---|---|---|---|---|
|
|
|
|
| Language | **Rust** (memory safe) | Go | C | C |
|
|
|
|
| Automatic HTTPS | **Built in**: HTTP-01, TLS-ALPN-01, DNS-01, ARI | Built in | certbot / module | `mod_md` |
|
|
|
|
| HTTP/3 | **On by default** | On by default | Enabled manually | — |
|
|
|
|
| WAF | **AssaultCuirass built in** (OWASP CRS v4) | Coraza plugin | ModSecurity module | ModSecurity module |
|
|
|
|
| Security headers | **On by default, per site** | Written in the Caddyfile | Written in the config | Written in the config |
|
|
|
|
| PHP | **Safe WordPress & Laravel presets** | `php_fastcgi` | `fastcgi_pass`, by hand | `mod_php`, php-fpm |
|
|
|
|
| TCP/UDP + SNI passthrough | **Built in** | `layer4` plugin | `stream` | — |
|
|
|
|
| Rate limiting | **Built in, per route** | Plugin | `limit_req` | Extra modules |
|
|
|
|
| Reload | **Validated, swapped atomically** | Graceful | `nginx -s reload` | `graceful` |
|
|
|
|
| Official web panel | **SPMPlus** | Third party | Third party | Third party |
|
|
|
|
| Configuration | **Slashfile**, one line per site | Caddyfile / JSON | `nginx.conf` | `httpd.conf`, `.htaccess` |
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## SPMPlus: reverse proxy manager
|
|
|
|
|
|
|
|
<img src="https://kubeman.unej.ac.id/geohot/slash/-/raw/main/brand/logo-spmplus-fix-with-text.png" alt="SPMPlus" width="240">
|
|
|
|
|
|
|
|
**SPMPlus (Slash Proxy Manager Plus)** is the web panel for Slash, a modern alternative to
|
|
|
|
Nginx Proxy Manager.
|
|
|
|
|
|
|
|
- **Preview before you apply:** every change is fully validated, shown as a diff, then
|
|
|
|
applied atomically. Each configuration version is recorded along with its audit log.
|
|
|
|
- **Proxy and panel run separately:** Slash keeps serving traffic while the panel is
|
|
|
|
being updated.
|
|
|
|
- **Hosts, Streams, Certificates and Access** in one place; test upstream connections
|
|
|
|
straight from the proxy's network.
|
|
|
|
- **Dashboard and Prometheus metrics**, access logs and an audit log.
|
|
|
|
- **Secure accounts:** multiple admins, passkeys, TOTP.
|
|
|
|
- **Lightweight:** two distroless Docker images, read-only and non-root, or a native
|
|
|
|
binary with systemd.
|
|
|
|
|
|
|
|
| | **SPMPlus** | Nginx Proxy Manager |
|
|
|
|
|---|---|---|
|
|
|
|
| Engine | **Slash (Rust)** | Nginx (OpenResty) |
|
|
|
|
| HTTP/3 | **Yes** | — |
|
|
|
|
| Compression | **zstd, Brotli, gzip** | gzip |
|
|
|
|
| WAF | **AssaultCuirass** | — |
|
|
|
|
| TCP/UDP streams | **Yes, plus TLS passthrough (SNI)** | Yes |
|
|
|
|
| Rate limiting | **Per route, from the panel** | Manual config |
|
|
|
|
| Applying changes | **Validation, diff preview, atomic swap, version history** | Write config, then reload |
|
|
|
|
| Metrics | **Dashboard + Prometheus** | — |
|
|
|
|
| Architecture | **Proxy and panel separated** | Single container |
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## Up and running in five minutes
|
|
|
|
|
|
|
|
**Slash on its own, with a Slashfile:**
|
|
|
|
|
|
|
|
```sh
|
|
|
|
git clone https://kubeman.unej.ac.id/geohot/slash.git && cd slash
|
|
|
|
docker build -f docker/Dockerfile.proxy --target final -t slash .
|
|
|
|
docker run -d --name slash --network host --restart unless-stopped \
|
|
|
|
-v "$PWD/Slashfile:/etc/slash/Slashfile:ro" -v slash-data:/data/proxy slash
|
|
|
|
```
|
|
|
|
|
|
|
|
**With the SPMPlus panel:**
|
|
|
|
|
|
|
|
```sh
|
|
|
|
git clone https://kubeman.unej.ac.id/geohot/slash.git && cd slash/docker
|
|
|
|
sudo ./gen-secrets.sh
|
|
|
|
docker compose up -d --build
|
|
|
|
docker compose logs panel | grep -i "setup token" | tail -1
|
|
|
|
```
|
|
|
|
|
|
|
|
Then open the panel through an SSH tunnel (`ssh -L 8443:127.0.0.1:8443 user@server`) at
|
|
|
|
`http://localhost:8443`.
|
|
|
|
|
|
|
|
**Requirements:** 64-bit Linux (x86_64 or ARM64). 1 vCPU and 512 MB of RAM are enough to
|
|
|
|
start; 2 vCPUs and 2 GB of RAM serve about 10,000 concurrent users. Ports 80, 443/tcp and
|
|
|
|
443/udp.
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## Documentation
|
|
|
|
|
|
|
|
| | |
|
|
|
|
|---|---|
|
|
|
|
| [README](https://kubeman.unej.ac.id/geohot/slash/-/blob/main/README.en.md) | Full guide and troubleshooting |
|
|
|
|
| [AssaultCuirass design](https://kubeman.unej.ac.id/geohot/slash/-/blob/main/docs/adr/0015-waf.md) | How the WAF works and how it was measured |
|
|
|
|
| [Streams design](https://kubeman.unej.ac.id/geohot/slash/-/blob/main/docs/adr/0016-streams.md) | TCP, UDP and TLS passthrough |
|
|
|
|
| [Slashfile reference](https://kubeman.unej.ac.id/geohot/slash/-/blob/main/docs/slashfile.md) | Sites, PHP, WAF, TCP/UDP (in Indonesian) |
|
|
|
|
| [Benchmarks](https://kubeman.unej.ac.id/geohot/slash/-/blob/main/docs/benchmarks.md) | Method and how to reproduce (in Indonesian) |
|
|
|
|
|
|
|
|
Open source, dual-licensed under [MIT](https://kubeman.unej.ac.id/geohot/slash/-/blob/main/LICENSE-MIT)
|
|
|
|
or [Apache-2.0](https://kubeman.unej.ac.id/geohot/slash/-/blob/main/LICENSE-APACHE).
|
|
|
|
© 2026 Agung Hendro. |