Skip to content

Instantly share code, notes, and snippets.

@byt3bl33d3r
Last active October 6, 2023 23:38
Show Gist options
  • Save byt3bl33d3r/054e5c183a46c6c021a4bb8f1901c143 to your computer and use it in GitHub Desktop.
Save byt3bl33d3r/054e5c183a46c6c021a4bb8f1901c143 to your computer and use it in GitHub Desktop.
Caddyfile reverse proxy example for C2 platforms
{
# This instructs Caddy to hit the LetsEncrypt staging endpoint, in production you should remove this.
acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
}
(proxy_upstream) {
# Enable access logging to STDOUT
log
# This is our list of naughty client User Agents that we don't want accessing our C2
@ua_denylist {
header User-Agent curl*
}
# This is our list of naughty IPs that we want to prevent from accessing our C2
@ip_denylist {
remote_ip 8.8.8.8/32
}
header {
-Server
+X-Robots-Tag "noindex, nofollow, nosnippet, noarchive"
+X-Content-Type-Options "nosniff"
}
# Respond with a 403 if the client has a User Agent defined in our naughty list
# Lot more you can do with this (e.g. redirect to seperate domain), check the docs
respond @ua_denylist "Forbidden" 403 {
close
}
# Respond with a 403 if the client has an IP defined in our naughty list
# Lot more you can do with this (e.g. redirect to seperate domain), check the docs
respond @ip_denylist "Forbidden" 403 {
close
}
# Reverse proxy to our host "c2platform" on port 80
# Caddy automatically adds a X-Forwarded-For header which is super useful for Cobalt Strike
reverse_proxy c2platform:80 {
header_up Host {upstream_hostport}
header_up X-Forwarded-Host {host}
header_up X-Forwarded-Port {port}
}
}
www.legitdomain.com {
# Use the proxy_upstream code snippet (defined above)
import proxy_upstream
}
legitdomain.com {
# Use the proxy_upstream code snippet (defined above)
import proxy_upstream
}
@XiaoliChan
Copy link

XiaoliChan commented Aug 26, 2022

I think the best way is to reject the request which is mismatched in C2 profile, not "ua_denylist". (Similar like RedWarden)

@XiaoliChan
Copy link

XiaoliChan commented Aug 26, 2022

Probably like this

@headers_matcher {
                header “headers in c2 profile” “headers value in c2 profile”
 }
reverse_proxy @headers_matcher "c2:port_bind"{
                header_up Host {upstream_hostport}
                header_up X-Forwarded-Host {host}
                header_up X-Forwarded-Port {port}
}
redir https://www.google.com #default is redirect to google.com

@DocBrown101
Copy link

I wanted to handle multiple user agents, so I decided to use a regex variant:

@ua_denylist {
  header_regexp User-Agent (?i)(go-http|python|Expanse|curl|nocom|node-fetch)
}

@mrexodia
Copy link

You can also write:

www.legitdomain.com, legitdomain.com {
        ...
}

That way you can get rid of the import statement.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment