mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-26 21:53:48 +03:00
caddyhttp: Support TLS key logging for debugging (#4808)
* Add SSL key logging. * Resolve merge conflict with master * Add Caddyfile support; various fixes * Also commit go.mod and go.sum, oops * Appease linter * Minor tweaks * Add doc comment Co-authored-by: Matt Holt <mholt@users.noreply.github.com>
This commit is contained in:
parent
74547f5bed
commit
616418281b
3 changed files with 87 additions and 40 deletions
|
@ -53,8 +53,7 @@ func init() {
|
|||
|
||||
// parseBind parses the bind directive. Syntax:
|
||||
//
|
||||
// bind <addresses...>
|
||||
//
|
||||
// bind <addresses...>
|
||||
func parseBind(h Helper) ([]ConfigValue, error) {
|
||||
var lnHosts []string
|
||||
for h.Next() {
|
||||
|
@ -65,28 +64,28 @@ func parseBind(h Helper) ([]ConfigValue, error) {
|
|||
|
||||
// parseTLS parses the tls directive. Syntax:
|
||||
//
|
||||
// tls [<email>|internal]|[<cert_file> <key_file>] {
|
||||
// protocols <min> [<max>]
|
||||
// ciphers <cipher_suites...>
|
||||
// curves <curves...>
|
||||
// client_auth {
|
||||
// mode [request|require|verify_if_given|require_and_verify]
|
||||
// trusted_ca_cert <base64_der>
|
||||
// trusted_ca_cert_file <filename>
|
||||
// trusted_leaf_cert <base64_der>
|
||||
// trusted_leaf_cert_file <filename>
|
||||
// }
|
||||
// alpn <values...>
|
||||
// load <paths...>
|
||||
// ca <acme_ca_endpoint>
|
||||
// ca_root <pem_file>
|
||||
// dns <provider_name> [...]
|
||||
// on_demand
|
||||
// eab <key_id> <mac_key>
|
||||
// issuer <module_name> [...]
|
||||
// get_certificate <module_name> [...]
|
||||
// }
|
||||
//
|
||||
// tls [<email>|internal]|[<cert_file> <key_file>] {
|
||||
// protocols <min> [<max>]
|
||||
// ciphers <cipher_suites...>
|
||||
// curves <curves...>
|
||||
// client_auth {
|
||||
// mode [request|require|verify_if_given|require_and_verify]
|
||||
// trusted_ca_cert <base64_der>
|
||||
// trusted_ca_cert_file <filename>
|
||||
// trusted_leaf_cert <base64_der>
|
||||
// trusted_leaf_cert_file <filename>
|
||||
// }
|
||||
// alpn <values...>
|
||||
// load <paths...>
|
||||
// ca <acme_ca_endpoint>
|
||||
// ca_root <pem_file>
|
||||
// dns <provider_name> [...]
|
||||
// on_demand
|
||||
// eab <key_id> <mac_key>
|
||||
// issuer <module_name> [...]
|
||||
// get_certificate <module_name> [...]
|
||||
// insecure_secrets_log <log_file>
|
||||
// }
|
||||
func parseTLS(h Helper) ([]ConfigValue, error) {
|
||||
cp := new(caddytls.ConnectionPolicy)
|
||||
var fileLoader caddytls.FileLoader
|
||||
|
@ -396,6 +395,12 @@ func parseTLS(h Helper) ([]ConfigValue, error) {
|
|||
}
|
||||
onDemand = true
|
||||
|
||||
case "insecure_secrets_log":
|
||||
if !h.NextArg() {
|
||||
return nil, h.ArgErr()
|
||||
}
|
||||
cp.InsecureSecretsLog = h.Val()
|
||||
|
||||
default:
|
||||
return nil, h.Errf("unknown subdirective: %s", h.Val())
|
||||
}
|
||||
|
@ -516,8 +521,7 @@ func parseTLS(h Helper) ([]ConfigValue, error) {
|
|||
|
||||
// parseRoot parses the root directive. Syntax:
|
||||
//
|
||||
// root [<matcher>] <path>
|
||||
//
|
||||
// root [<matcher>] <path>
|
||||
func parseRoot(h Helper) (caddyhttp.MiddlewareHandler, error) {
|
||||
var root string
|
||||
for h.Next() {
|
||||
|
@ -695,12 +699,11 @@ func parseHandleErrors(h Helper) ([]ConfigValue, error) {
|
|||
|
||||
// parseLog parses the log directive. Syntax:
|
||||
//
|
||||
// log {
|
||||
// output <writer_module> ...
|
||||
// format <encoder_module> ...
|
||||
// level <level>
|
||||
// }
|
||||
//
|
||||
// log {
|
||||
// output <writer_module> ...
|
||||
// format <encoder_module> ...
|
||||
// level <level>
|
||||
// }
|
||||
func parseLog(h Helper) ([]ConfigValue, error) {
|
||||
return parseLogHelper(h, nil)
|
||||
}
|
||||
|
|
|
@ -421,13 +421,13 @@ func parseOCSPStaplingOptions(d *caddyfile.Dispenser, _ any) (any, error) {
|
|||
|
||||
// parseLogOptions parses the global log option. Syntax:
|
||||
//
|
||||
// log [name] {
|
||||
// output <writer_module> ...
|
||||
// format <encoder_module> ...
|
||||
// level <level>
|
||||
// include <namespaces...>
|
||||
// exclude <namespaces...>
|
||||
// }
|
||||
// log [name] {
|
||||
// output <writer_module> ...
|
||||
// format <encoder_module> ...
|
||||
// level <level>
|
||||
// include <namespaces...>
|
||||
// exclude <namespaces...>
|
||||
// }
|
||||
//
|
||||
// When the name argument is unspecified, this directive modifies the default
|
||||
// logger.
|
||||
|
|
|
@ -20,11 +20,14 @@ import (
|
|||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/caddyserver/caddy/v2"
|
||||
"github.com/mholt/acmez"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -156,6 +159,16 @@ type ConnectionPolicy struct {
|
|||
// is no policy configured for the empty SNI value.
|
||||
DefaultSNI string `json:"default_sni,omitempty"`
|
||||
|
||||
// Also known as "SSLKEYLOGFILE", TLS secrets will be written to
|
||||
// this file in NSS key log format which can then be parsed by
|
||||
// Wireshark and other tools. This is INSECURE as it allows other
|
||||
// programs or tools to decrypt TLS connections. However, this
|
||||
// capability can be useful for debugging and troubleshooting.
|
||||
// **ENABLING THIS LOG COMPROMISES SECURITY!**
|
||||
//
|
||||
// This feature is EXPERIMENTAL and subject to change or removal.
|
||||
InsecureSecretsLog string `json:"insecure_secrets_log,omitempty"`
|
||||
|
||||
// TLSConfig is the fully-formed, standard lib TLS config
|
||||
// used to serve TLS connections. Provision all
|
||||
// ConnectionPolicies to populate this. It is exported only
|
||||
|
@ -280,6 +293,30 @@ func (p *ConnectionPolicy) buildStandardTLSConfig(ctx caddy.Context) error {
|
|||
}
|
||||
}
|
||||
|
||||
if p.InsecureSecretsLog != "" {
|
||||
filename, err := caddy.NewReplacer().ReplaceOrErr(p.InsecureSecretsLog, true, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
filename, err = filepath.Abs(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logFile, _, err := secretsLogPool.LoadOrNew(filename, func() (caddy.Destructor, error) {
|
||||
w, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0600)
|
||||
return destructableWriter{w}, err
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctx.OnCancel(func() { _, _ = secretsLogPool.Delete(filename) })
|
||||
|
||||
cfg.KeyLogWriter = logFile.(io.Writer)
|
||||
|
||||
tlsApp.logger.Warn("TLS SECURITY COMPROMISED: secrets logging is enabled!",
|
||||
zap.String("log_filename", filename))
|
||||
}
|
||||
|
||||
setDefaultTLSParams(cfg)
|
||||
|
||||
p.TLSConfig = cfg
|
||||
|
@ -297,7 +334,8 @@ func (p ConnectionPolicy) SettingsEmpty() bool {
|
|||
p.ProtocolMin == "" &&
|
||||
p.ProtocolMax == "" &&
|
||||
p.ClientAuthentication == nil &&
|
||||
p.DefaultSNI == ""
|
||||
p.DefaultSNI == "" &&
|
||||
p.InsecureSecretsLog == ""
|
||||
}
|
||||
|
||||
// ClientAuthentication configures TLS client auth.
|
||||
|
@ -542,3 +580,9 @@ type ClientCertificateVerifier interface {
|
|||
}
|
||||
|
||||
var defaultALPN = []string{"h2", "http/1.1"}
|
||||
|
||||
type destructableWriter struct{ *os.File }
|
||||
|
||||
func (d destructableWriter) Destruct() error { return d.Close() }
|
||||
|
||||
var secretsLogPool = caddy.NewUsagePool()
|
||||
|
|
Loading…
Reference in a new issue