Release old bindings when HTTPS redirects are disabled

1. The problem I’m having:

I cannot set new bindings in the “listen”-section of a server if both of these conditions occur:

  • the server is configured to disable automatic HTTPS redirects
  • the new address is part of the old one (0.0.0.0:443 → 172.17.0.1:443)

Is this behavior intended?

2. Error messages and/or full log output:

-> % sudo ./caddy_2.7.4 run --config "caddy-demo.json"
2023/12/06 15:13:13.672 INFO    using provided configuration    {"config_file": "caddy-demo.json", "config_adapter": ""}
2023/12/06 15:13:13.673 INFO    redirected default logger       {"from": "stderr", "to": "stdout"}
2023/12/06 15:13:13.677 INFO    admin   admin endpoint started  {"address": "localhost:2019", "enforce_origin": false, "origins": ["//localhost"]}
2023/12/06 15:13:13.682 WARN    http.auto_https automatic HTTP->HTTPS redirects are disabled    {"server_name": "external-interfaces"}
2023/12/06 15:13:13.682 DEBUG   http.auto_https adjusted config {"tls": {"automation":{"policies":[{"key_type":"rsa2048","on_demand":true}],"on_demand":{"rate_limit":{"interval":60000000000,"burst":5}}}}, "http": {"servers":{"external-interfaces":{"listen":["0.0.0.0:80","0.0.0.0:443"],"routes":[{"handle":[{"handler":"static_response","status_code":"200"}]}],"tls_connection_policies":[{"protocol_min":"tls1.2"}],"automatic_https":{"disable_redirects":true}}}}}
2023/12/06 15:13:13.684 INFO    tls.cache.maintenance   started background certificate maintenance      {"cache": "0xc00065c500"}
2023/12/06 15:13:13.699 INFO    pki.ca.device_ca        root certificate is already trusted by system   {"path": "storage:pki/authorities/device_ca/root.crt"}
2023/12/06 15:13:13.701 INFO    tls     cleaning storage unit   {"description": "FileStorage:/root/.local/share/caddy"}
2023/12/06 15:13:13.701 DEBUG   http    starting server loop    {"address": "[::]:80", "tls": false, "http3": false}
2023/12/06 15:13:13.701 INFO    tls     finished cleaning storage units
2023/12/06 15:13:13.704 INFO    http    enabling HTTP/3 listener        {"addr": "0.0.0.0:443"}
2023/12/06 15:13:13.706 DEBUG   http    starting server loop    {"address": "[::]:443", "tls": true, "http3": true}
2023/12/06 15:13:13.706 INFO    http.log        server running  {"name": "external-interfaces", "protocols": ["h1", "h2", "h3"]}
2023/12/06 15:13:13.706 INFO    autosaved config (load with --resume flag)      {"file": "/root/.config/caddy/autosave.json"}
2023/12/06 15:13:13.706 INFO    serving initial configuration
2023/12/06 15:13:18.659 INFO    admin.api       received request        {"method": "PATCH", "host": "localhost", "uri": "/config/apps/http/servers/external-interfaces/listen", "remote_ip": "127.0.0.1", "remote_port": "49400", "headers": {"Accept":["*/*"],"Content-Length":["32"],"Content-Type":["application/json"],"User-Agent":["curl/7.68.0"]}}
2023/12/06 15:13:18.660 INFO    admin   admin endpoint started  {"address": "localhost:2019", "enforce_origin": false, "origins": ["//localhost"]}
2023/12/06 15:13:18.661 WARN    http.auto_https automatic HTTP->HTTPS redirects are disabled    {"server_name": "external-interfaces"}
2023/12/06 15:13:18.661 DEBUG   http.auto_https adjusted config {"tls": {"automation":{"policies":[{"key_type":"rsa2048","on_demand":true}],"on_demand":{"rate_limit":{"interval":60000000000,"burst":5}}}}, "http": {"servers":{"external-interfaces":{"listen":["0.0.0.0:80","172.17.0.1:443"],"routes":[{"handle":[{"handler":"static_response","status_code":"200"}]}],"tls_connection_policies":[{"protocol_min":"tls1.2"}],"automatic_https":{"disable_redirects":true}}}}}
2023/12/06 15:13:18.661 INFO    pki.ca.device_ca        root certificate is already trusted by system   {"path": "storage:pki/authorities/device_ca/root.crt"}
2023/12/06 15:13:18.661 DEBUG   http    starting server loop    {"address": "[::]:80", "tls": false, "http3": false}
2023/12/06 15:13:18.661 INFO    http    enabling HTTP/3 listener        {"addr": "172.17.0.1:443"}
2023/12/06 15:13:18.661 ERROR   admin.api       request error   {"error": "loading new config: http app module: start: listen udp 172.17.0.1:443: bind: address already in use", "status_code": 500}
2023/12/06 15:13:18.663 INFO    admin   stopped previous server {"address": "localhost:2019"}
-> % sudo curl -X PATCH -v -H "Content-Type:application/json" -H 'Host: localhost' http://localhost:2019/config/apps/http/servers/external-interfaces/listen --data '["0.0.0.0:80", "172.17.0.1:443"]'
*   Trying 127.0.0.1:2019...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 2019 (#0)
> PATCH /config/apps/http/servers/external-interfaces/listen HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
> Content-Type:application/json
> Content-Length: 32
>
* upload completely sent off: 32 out of 32 bytes
* Mark bundle as not supporting multiuse
< HTTP/1.1 500 Internal Server Error
< Content-Type: application/json
< Date: Wed, 06 Dec 2023 15:13:18 GMT
< Content-Length: 112
< Connection: close
<
{"error":"loading new config: http app module: start: listen udp 172.17.0.1:443: bind: address already in use"}
* Closing connection 0

3. Caddy version:

v2.7.4 h1:J8nisjdOxnYHXlorUKXY75Gr6iBfudfoGhrJ8t7/flI=

4. How I installed and ran Caddy:

xcaddy build v2.7.4 --with github.com/RussellLuo/caddy-ext/ratelimit

a. System environment:

WSL2.0

b. Command:

sudo ./caddy_2.7.4 run --config "caddy-demo.json"

d. My complete Caddy config:

{
  "apps": {
    "http": {
      "servers": {
        "external-interfaces": {
          "automatic_https": {
            "disable_redirects": true
          },
          "listen": [
            "0.0.0.0:80",
            "0.0.0.0:443"
          ],
          "routes": [
            {
              "handle": [
                {
                  "handler": "static_response",
                  "status_code": "200"
                }
              ],
              "match": [
                {
                  "path": [
                    "/test*"
                  ]
                }
              ]
            }
          ],
          "tls_connection_policies": [
            {
              "protocol_min": "tls1.2"
            }
          ]
        }
      }
    },
    "tls": {
      "automation": {
        "policies": [
          {
            "on_demand": true,
            "key_type": "rsa2048",
            "issuers": [
              {
                "module": "internal",
                "ca": "device_ca"
              }
            ]
          }
        ],
        "on_demand": {
          "rate_limit": {
            "interval": "1m",
            "burst": 5
          }
        }
      }
    },
    "pki": {
      "certificate_authorities": {
        "device_ca": {
          "root_common_name": "Standard Root CA",
          "intermediate_common_name": "Standard Intermediate CA"
        }
      }
    }
  },
  "logging": {
    "logs": {
      "default": {
        "writer": {
          "output": "stdout"
        },
        "encoder": {
          "format": "console"
        },
        "level": "debug"
      }
    }
  },
  "admin": {
    "listen": "localhost:2019",
    "origins": [
      "localhost"
    ]
  }
}```


### 5. Links to relevant resources:
<!-- Optional, but can help get us on the same page quickly. -->

A workaround I figured out was to first delete the :443 address in the “listen” section and then set the new address.

I don’t think it’s intentional. @Mohammed90 what do you think? I probably need to adjust the listener usagepool to account for catch-all addresses or something?

I don’t see how this could work. Caddy is designed to do graceful reloads by keeping the first config running until the second one is ready to go. Caddy hands off the listeners from the previous to the next config if they’re the same, but if they differ then that handoff is not possible and the new config has to create a new listener. But if they overlap then you’ll get an error.

That is true…

I think there might be a socket option at least on Linux we can set to enable this behavior. Not sure how to do it for Windows/Mac.

I agree with @francislavoie in his reasoning that the issue is overlapping listener addresses. There’s the SO_REUSEADDR option which could resolve the issue:

It exists on Linux and Windows (not sure about other unices). However, it seems that this option is a can of worms, and we need to be careful.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.