httpcaddyfile: Skip TLS APs for HTTP-only hosts (fix #3977)

This is probably an invasive change, but existing tests continue to pass.
It seems to make sense this way. There is likely an edge case I haven't
considered.
This commit is contained in:
Matthew Holt 2021-01-19 14:16:06 -07:00
parent 8f6f9865d4
commit d68cff8eb6
No known key found for this signature in database
GPG key ID: 2A349DD577D586A5
3 changed files with 88 additions and 10 deletions

View file

@ -409,7 +409,7 @@ func (st *ServerType) serversFromPairings(
var iLongestHost, jLongestHost string var iLongestHost, jLongestHost string
var iWildcardHost, jWildcardHost bool var iWildcardHost, jWildcardHost bool
for _, addr := range p.serverBlocks[i].keys { for _, addr := range p.serverBlocks[i].keys {
if strings.Contains(addr.Host, "*.") { if strings.Contains(addr.Host, "*") {
iWildcardHost = true iWildcardHost = true
} }
if specificity(addr.Host) > specificity(iLongestHost) { if specificity(addr.Host) > specificity(iLongestHost) {
@ -420,7 +420,7 @@ func (st *ServerType) serversFromPairings(
} }
} }
for _, addr := range p.serverBlocks[j].keys { for _, addr := range p.serverBlocks[j].keys {
if strings.Contains(addr.Host, "*.") { if strings.Contains(addr.Host, "*") {
jWildcardHost = true jWildcardHost = true
} }
if specificity(addr.Host) > specificity(jLongestHost) { if specificity(addr.Host) > specificity(jLongestHost) {
@ -500,6 +500,8 @@ func (st *ServerType) serversFromPairings(
} }
for _, addr := range sblock.keys { for _, addr := range sblock.keys {
// if server only uses HTTPS port, auto-HTTPS will not apply
if listenersUseAnyPortOtherThan(srv.Listen, httpPort) {
// exclude any hosts that were defined explicitly with "http://" // exclude any hosts that were defined explicitly with "http://"
// in the key from automated cert management (issue #2998) // in the key from automated cert management (issue #2998)
if addr.Scheme == "http" && addr.Host != "" { if addr.Scheme == "http" && addr.Host != "" {
@ -510,6 +512,8 @@ func (st *ServerType) serversFromPairings(
srv.AutoHTTPS.Skip = append(srv.AutoHTTPS.Skip, addr.Host) srv.AutoHTTPS.Skip = append(srv.AutoHTTPS.Skip, addr.Host)
} }
} }
}
// we'll need to remember if the address qualifies for auto-HTTPS, so we // we'll need to remember if the address qualifies for auto-HTTPS, so we
// can add a TLS conn policy if necessary // can add a TLS conn policy if necessary
if addr.Scheme == "https" || if addr.Scheme == "https" ||
@ -1183,6 +1187,26 @@ func sliceContains(haystack []string, needle string) bool {
return false return false
} }
// listenersUseAnyPortOtherThan returns true if there are any
// listeners in addresses that use a port which is not otherPort.
// Mostly borrowed from unexported method in caddyhttp package.
func listenersUseAnyPortOtherThan(addresses []string, otherPort string) bool {
otherPortInt, err := strconv.Atoi(otherPort)
if err != nil {
return false
}
for _, lnAddr := range addresses {
laddrs, err := caddy.ParseNetworkAddress(lnAddr)
if err != nil {
continue
}
if uint(otherPortInt) > laddrs.EndPort || uint(otherPortInt) < laddrs.StartPort {
return true
}
}
return false
}
// specificity returns len(s) minus any wildcards (*) and // specificity returns len(s) minus any wildcards (*) and
// placeholders ({...}). Basically, it's a length count // placeholders ({...}). Basically, it's a length count
// that penalizes the use of wildcards and placeholders. // that penalizes the use of wildcards and placeholders.

View file

@ -40,6 +40,10 @@ func (st ServerType) buildTLSApp(
tlsApp := &caddytls.TLS{CertificatesRaw: make(caddy.ModuleMap)} tlsApp := &caddytls.TLS{CertificatesRaw: make(caddy.ModuleMap)}
var certLoaders []caddytls.CertificateLoader var certLoaders []caddytls.CertificateLoader
httpPort := strconv.Itoa(caddyhttp.DefaultHTTPPort)
if hp, ok := options["http_port"].(int); ok {
httpPort = strconv.Itoa(hp)
}
httpsPort := strconv.Itoa(caddyhttp.DefaultHTTPSPort) httpsPort := strconv.Itoa(caddyhttp.DefaultHTTPSPort)
if hsp, ok := options["https_port"].(int); ok { if hsp, ok := options["https_port"].(int); ok {
httpsPort = strconv.Itoa(hsp) httpsPort = strconv.Itoa(hsp)
@ -91,6 +95,11 @@ func (st ServerType) buildTLSApp(
} }
for _, p := range pairings { for _, p := range pairings {
// avoid setting up TLS automation policies for a server that is HTTP-only
if !listenersUseAnyPortOtherThan(p.addresses, httpPort) {
continue
}
for _, sblock := range p.serverBlocks { for _, sblock := range p.serverBlocks {
// get values that populate an automation policy for this block // get values that populate an automation policy for this block
ap, err := newBaseAutomationPolicy(options, warnings, true) ap, err := newBaseAutomationPolicy(options, warnings, true)

View file

@ -0,0 +1,45 @@
# https://github.com/caddyserver/caddy/issues/3977
http://* {
respond "Hello, world!"
}
----------
{
"apps": {
"http": {
"servers": {
"srv0": {
"listen": [
":80"
],
"routes": [
{
"match": [
{
"host": [
"*"
]
}
],
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"body": "Hello, world!",
"handler": "static_response"
}
]
}
]
}
],
"terminal": true
}
]
}
}
}
}
}