Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
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
23142 months 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

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:

caddy run --config /etc/caddy/redirector.caddy --adapter caddyfile

To reload a running instance with an updated config:

caddy reload --config /etc/caddy/redirector.caddy --adapter caddyfile

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

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:

# /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:

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

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

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:

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

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

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:

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

# 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
Download Tool