Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CaddySmith — Generate Caddy redirector configs from Cobalt Strike or Sliver C2 profiles. | Kitploit
Tools/GitHubGitHub/icecubesandwich/caddysmith
Penetration Testing FrameworksWeb Proxies & InterceptionIDS/IPS EvasionCommand and ControlRed TeamingPayload Development
GitHubicecubesandwich/caddysmith

CaddySmith

Generate Caddy redirector configs from Cobalt Strike or Sliver C2 profiles.

View Repository
231 month agoReviewed by Kitploit

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CaddySmith

CaddySmith is a small Python script that reads a Cobalt Strike or Sliver C2 profile and forges a Caddy web server config out of it. The generated Caddyfile turns a regular Linux box into a redirector: legitimate beacon traffic gets reverse-proxied to your team server, and anything else (scanners, search bots, blue team probes, random curl) gets bounced to a decoy URL.

I wrote this because Caddy is a much friendlier web server to stand up quickly than Apache, single static binary, automatic Let's Encrypt certs, no a2enmod dance.

Authorized engagements only. This is offensive security tooling. Only run it against environments you have written permission to test.

Supported profile formats

CaddySmith auto-detects the format from the file contents:

  • Cobalt Strike — the classic text format with set uri "/foo" directives. Each HTTP-GET / HTTP-POST URI becomes its own exact-path route with the profile's client headers enforced.
  • Sliver — the JSON implant config exported from Sliver. Sliver doesn't have fixed URIs; it generates them at beacon-build time from path / file / extension lists. CaddySmith handles this by matching the top-level path prefixes as globs (e.g. path /api* /static* /resources*) and doing a substring match on the Chrome build number from the UA (which survives Sliver's per-platform UA rewrites).

You can also force a specific parser with --profile-type cobaltstrike or --profile-type sliver.

What it does

Given a profile file, the script pulls out:

  • The User-Agent string
  • URIs (CS) or path prefixes (Sliver)
  • Client-side headers (CS only — Sliver doesn't dictate specific headers)
  • The Host header (used as the redirector's domain name if you don't pass --server-name)
  • Whether staging is enabled (CS only — set host_stage)

Then it builds a Caddyfile that:

  1. (Optional) Returns 403 to plain HTTP traffic
  2. Blocks ~15 known-bad user agents (curl, nmap, sqlmap, Googlebot, etc.)
  3. Blocks direct-IP access and any HTTP method that isn't GET/POST
  4. Reverse-proxies only the profile's URIs (or prefixes for Sliver), gated on the matching User-Agent
  5. Blocks common scanner probe paths (.env, /wp-admin, .php, etc.)
  6. Redirects everything else to your decoy URL

Requirements

  • Python 3.7+ (uses only the standard library, no pip install needed)
  • Caddy 2.x on the redirector itself (install guide)

Quick start

root@kitploit:~
python3 caddysmith.py my.profile \
    --backend https://teamserver.internal:443 \
    --decoy   https://www.example.com/ \
    --server-name redirector.example.com \
    --email   [email protected] \
    --forbid-http \
    -o redirector.caddy

This writes the generated config to redirector.caddy and prints a summary of what it did to stderr.

Deploying the generated config

Option A: Run the Caddyfile directly

Copy the generated file to the redirector and run Caddy against it. You need the --adapter caddyfile flag because Caddy defaults to JSON config:

root@kitploit:~
caddy run --config /etc/caddy/redirector.caddy --adapter caddyfile

To reload a running instance with an updated config:

root@kitploit:~
caddy reload --config /etc/caddy/redirector.caddy --adapter caddyfile

If Caddy warns about formatting inconsistencies, clean them up with:

root@kitploit:~
caddy fmt --overwrite /etc/caddy/redirector.caddy

Option B: Import from a main Caddyfile

Drop the file in /etc/caddy/ and import it from your main Caddyfile:

root@kitploit:~
# /etc/caddy/Caddyfile
import /etc/caddy/redirector.caddy

If you passed --email (recommended), the generated snippet already contains the global options block, so the main Caddyfile only needs the import line. If you didn't, add the email manually to a { } block above the import.

Then validate and reload:

root@kitploit:~
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy

Caddy will auto-provision a Let's Encrypt cert for the domain in --server-name as long as the A record points at the redirector.

All the flags

Policy modes

  • strict (default) — checks User-Agent, all client headers, direct-IP, HTTP method, and probe paths
  • lax — only blocks bad user agents, no per-route header matching
  • none — proxies any request to a profile URI, no filtering

Strict is what you usually want. Lax is useful when you're debugging why a real beacon isn't connecting.

A worked example

Say you have a profile that mimics an Amazon endpoint and you want to deploy it on redirector.0xtb.sh:

root@kitploit:~
python3 caddysmith.py amazon.profile \
    --backend https://10.1.1.10:443 \
    --decoy   https://www.amazon.com/ \
    --server-name redirector.0xtb.sh \
    --forbid-http \
    --policy strict \
    -o /etc/caddy/redirector.caddy

The summary shows you exactly which routes got built, e.g.:

root@kitploit:~
Routes built:   2
  - [profile-get] /broadcast
  - [profile-post] /1/events/com.amazon.csm.csa.prod

If you regenerate and see no routes, the script probably failed to parse your profile — check the warnings on stderr.

Sliver example

For a Sliver implant config (JSON):

root@kitploit:~
python3 caddysmith.py sliver-implant.json \
    --backend https://10.1.1.10:443 \
    --decoy   https://www.amazon.com/ \
    --server-name redirector.0xtb.sh \
    --email   [email protected] \
    --forbid-http \
    --policy strict \
    -o /etc/caddy/redirector.caddy

The summary will tell you that Sliver was detected and show the prefix route:

root@kitploit:~
Profile type:   sliver
Routes built:   1
  - [sliver] /api /public /resources /services /static (prefix)

Because Sliver generates URIs randomly from path × file × extension combinations, the generated path matcher uses prefix globs (path /api* /public* /resources* /services* /static*) rather than exact paths. The User-Agent matcher uses a substring of the Chrome build number (e.g. 3921.146), which Sliver preserves across its per-platform UA rewrites.

Smoke tests after you deploy

root@kitploit:~
# Plain HTTP should be 403'd (if you used --forbid-http)
curl -I http://redirector.0xtb.sh/

# Bare hostname should redirect to the decoy
curl -kI https://redirector.0xtb.sh/

# Bad UA should also redirect
curl -kI -A "curl/8.4.0" https://redirector.0xtb.sh/broadcast

# A request with the right UA + path should proxy through (200)
# You need to also send all the profile's client headers in strict mode.

Known limitations

  • Staging rules aren't generated (Cobalt Strike). If your CS profile has set host_stage "true" (or doesn't set it at all), the script will warn you and skip stager URIs. Add set host_stage "false"; to your profile, or pass the stager URIs explicitly via --extra-uri.
  • Sliver prefix matching is wider than CS exact matching. With Sliver, the proxy route claims any URL starting with /api, /static, etc. Scanner probes that happen to use those prefixes (e.g. /api/.env) will be sent to the team server rather than blocked locally — but Sliver's own HTTP transport authenticates via implant ID, so unauthorized requests get rejected at the C2 layer. The UA gating still keeps most scanners out.
  • One backend per run. Every route proxies to the same --backend. If you need multiple team servers, run the script multiple times and merge by hand.
  • Profile URI parsing is line-based (Cobalt Strike). set uri "/path1 /path2"; works (multiple paths on one line), but unusual formatting might trip up the parser. Check the route list in the summary to confirm.
  • HTTPS backend cert verification is off by default. Team servers usually have self-signed certs, so the generated config includes tls_insecure_skip_verify. If your backend has a real cert, delete that line from the generated file.

Credits

The Apache-based Malleable-Redirector was the starting point for what this script generates, same three-track URI model (profile URIs / extra URIs / lax URIs), same policy modes, same general layout. CaddySmith just translates the output to Caddy syntax instead of Apache .htaccess.

License

MIT

Download Tool
FlagDefaultWhat it does
profile(required)Path to the .profile file
--backendhttps://teamserver.local:443Where to proxy matched traffic
--decoyhttps://www.example.com/Where unmatched traffic redirects
--server-namec2.example.comYour redirector's domain name
--policystrictstrict, lax, or none
--profile-typeautoForce cobaltstrike or sliver (default: auto-detect)
--extra-uri PATH—Extra URI to proxy (with UA check). Can repeat.
--lax-uri PATH—Extra URI to proxy (no checks). Can repeat.
--allow-ua STRING—Extra UA allowed on --extra-uri routes. Can repeat.
--forbid-httpoffReturn 403 on plain HTTP
--email EMAIL—Email for Let's Encrypt registration and renewal notices
-o, --output FILEstdoutWrite the config to a file