Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

using 0.0.0.0 and [::] as default_bind/bind results in double binding 0.0.0.0 and [::] in h3/UDP and crash #5692

Open
Zoey2936 opened this issue Aug 4, 2023 · 6 comments
Labels
bug 🐞 Something isn't working

Comments

@Zoey2936
Copy link

Zoey2936 commented Aug 4, 2023

Hello, if I run one of this Caddyfiles:

{
        debug
        default_bind 0.0.0.0 [::]
        servers 0.0.0.0:443 {
                protocols h1 h2 h2c h3
        }
        servers [::]:443 {
                protocols h1 h2 h2c h3
        }
}

example.com {
        respond "Hello!"
}
{
        debug
        default_bind 0.0.0.0 [::]
}

example.com {
        respond "Hello!"
}
example.com {
        bind 0.0.0.0 [::]
        respond "Hello!"
}

it results in (the first caddyfile):

root@PC-Zoey:~# caddy version
v2.7.2 h1:QqThyoyUFAv1B7A2NMeaWlz7xmgKqU49PXBX08A+6xg=
root@PC-Zoey:~# caddy run --adapter caddyfile --config t
2023/08/04 16:34:42.122 INFO    using provided configuration    {"config_file": "t", "config_adapter": "caddyfile"}
2023/08/04 16:34:42.124 INFO    admin   admin endpoint started  {"address": "localhost:2019", "enforce_origin": false, "origins": ["//[::1]:2019", "//127.0.0.1:2019", "//localhost:2019"]}
2023/08/04 16:34:42.124 INFO    http.auto_https server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS {"server_name": "srv0", "https_port": 443}
2023/08/04 16:34:42.124 INFO    http.auto_https enabling automatic HTTP->HTTPS redirects        {"server_name": "srv0"}
2023/08/04 16:34:42.124 DEBUG   http.auto_https adjusted config {"tls": {"automation":{"policies":[{}]}}, "http": {"servers":{"remaining_auto_https_redirects":{"listen":["[::]:80"],"routes":[{},{}]},"srv0":{"listen":["0.0.0.0:443","[::]:443"],"routes":[{"handle":[{"handler":"subroute","routes":[{"handle":[{"body":"Hello!","handler":"static_response"}]}]}],"terminal":true}],"tls_connection_policies":[{}],"automatic_https":{},"protocols":["h1","h2","h2c","h3"]}}}}
2023/08/04 16:34:42.124 INFO    tls.cache.maintenance   started background certificate maintenance      {"cache": "0xc0003c7180"}
2023/08/04 16:34:42.124 INFO    http    enabling HTTP/3 listener        {"addr": "0.0.0.0:443"}
2023/08/04 16:34:42.124 INFO    tls     cleaning storage unit   {"description": "FileStorage:/root/.local/share/caddy"}
2023/08/04 16:34:42.124 DEBUG   http    starting server loop    {"address": "[::]:443", "tls": true, "http3": true}
2023/08/04 16:34:42.124 INFO    http    enabling HTTP/3 listener        {"addr": "[::]:443"}
2023/08/04 16:34:42.124 INFO    tls.cache.maintenance   stopped background certificate maintenance      {"cache": "0xc0003c7180"}
2023/08/04 16:34:42.124 INFO    tls     finished cleaning storage units
Error: loading initial config: loading new config: http app module: start: listen udp 0.0.0.0:443: bind: address already in use
root@PC-Zoey:~# caddy version
2.6.2
root@PC-Zoey:~# caddy run --adapter caddyfile --config t
2023/08/04 16:36:21.641 INFO    using provided configuration    {"config_file": "t", "config_adapter": "caddyfile"}
2023/08/04 16:36:21.643 INFO    admin   admin endpoint started  {"address": "localhost:2019", "enforce_origin": false, "origins": ["//127.0.0.1:2019", "//localhost:2019", "//[::1]:2019"]}
2023/08/04 16:36:21.643 INFO    http    server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS {"server_name": "srv0", "https_port": 443}
2023/08/04 16:36:21.643 INFO    http    enabling automatic HTTP->HTTPS redirects        {"server_name": "srv0"}
2023/08/04 16:36:21.643 INFO    tls.cache.maintenance   started background certificate maintenance      {"cache": "0xc000734b60"}
2023/08/04 16:36:21.644 DEBUG   http    starting server loop    {"address": "[::]:80", "tls": false, "http3": false}
2023/08/04 16:36:21.644 INFO    http.log        server running  {"name": "remaining_auto_https_redirects", "protocols": ["h1", "h2", "h3"]}
2023/08/04 16:36:21.644 INFO    tls     cleaning storage unit   {"description": "FileStorage:/root/.local/share/caddy"}
2023/08/04 16:36:21.644 INFO    http    enabling HTTP/3 listener        {"addr": "0.0.0.0:443"}
2023/08/04 16:36:21.644 INFO    failed to sufficiently increase receive buffer size (was: 208 kiB, wanted: 2048 kiB, got: 416 kiB). See https://github.com/lucas-clemente/quic-go/wiki/UDP-Receive-Buffer-Size for details.
2023/08/04 16:36:21.644 INFO    tls     finished cleaning storage units
2023/08/04 16:36:21.644 DEBUG   http    starting server loop    {"address": "[::]:443", "tls": true, "http3": true}
2023/08/04 16:36:21.644 INFO    http    enabling HTTP/3 listener        {"addr": "[::]:443"}
2023/08/04 16:36:21.644 INFO    tls.cache.maintenance   stopped background certificate maintenance      {"cache": "0xc000734b60"}
Error: loading initial config: loading new config: http app module: start: listen udp 0.0.0.0:443: bind: address already in use

But if I remove h3 from the protocols directive or if I remove the default_bind directive, it works. The same errors appear if I use bind 0.0.0.0 [::] inside the example.com host instead of setting the default_bind directive as a global option. And yes, UDP on port 443 is not used, I've tested it inside docker alpine, WSL Debian and alpine. netstat output on Debian WSL:

root@PC-Zoey:~# netstat -tulpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:49443         0.0.0.0:*               LISTEN      -
tcp        0      0 127.0.0.1:49000         0.0.0.0:*               LISTEN      -
tcp6       0      0 :::8000                 :::*                    LISTEN      -

(sorry for the edits, but I've tried to make the caddyfile smaller, so it can be clearly seen where the problem is)

Update 1: these caddyfiles also work, so it seems that the crash only appears with multiple bind IPs:

{
        debug
        default_bind 0.0.0.0
        servers 0.0.0.0:443 {
                protocols h1 h2 h2c h3
        }
}

example.com {
        respond "Hello!"
}
{
        debug
        default_bind [::]
        servers [::]:443 {
                protocols h1 h2 h2c h3
        }
}

example.com {
        respond "Hello!"
}

Update 2: these caddyfiles also don't work:

{
        default_bind 127.0.0.1 [::]
}

example.com {
        tls internal {
                on_demand
        }
        respond "Hello!"
}

Error: loading initial config: loading new config: http app module: start: listen udp 0.0.0.0:443: bind: address already in use - it seems like [::] is handles by caddy on UDP as "all" IPv4 and IPv6 IPs, even if it should only handle "all" IPv6 IPs. Not sure if 0.0.0.0 is also handled as IPv6

{
        default_bind 0.0.0.0 [::1]
}

example.com {
        tls internal {
                on_demand
        }
        respond "Hello!"
}

Error: loading initial config: loading new config: http app module: start: listen udp [::1]:443: bind: address already in use

Update 3: this caddy file works, so maybe 0.0.0.0 already includes [::] in UDP while [::] included 0.0.0.0 in UDP, so that if 0.0.0.0 [::] is used, it tries to bind 0.0.0.0 and [::] twice (or at least using [::] includes [::] AND 0.0.0.0)? (again, only in udp/h3 with h3 disabled, all caddyfiles I showed here work.) So Caddy handles tcp and udp binds differently?:

{
        default_bind [::1] 127.0.0.1
}

example.com {
        tls internal {
                on_demand
        }
        respond "Hello!"
}

Update 4: Interesting 0.0.0.0 seems to include [::] on TCP AND UDP and [::] also seems to include 0.0.0.0 on TCP AND UDP, but only on UDP it causes double binding, which causes a crash

@Zoey2936 Zoey2936 changed the title default_bind/bind does not work with h3 default_bind/bind does not work with h3, if there are multiple bind IPs Aug 4, 2023
@Zoey2936 Zoey2936 changed the title default_bind/bind does not work with h3, if there are multiple bind IPs using 0.0.0.0 and [::] as default_bind/bind results in double binding 0.0.0.0 and [::] in h3/udp? Aug 4, 2023
@Zoey2936 Zoey2936 changed the title using 0.0.0.0 and [::] as default_bind/bind results in double binding 0.0.0.0 and [::] in h3/udp? using 0.0.0.0 and [::] as default_bind/bind results in double binding 0.0.0.0 and [::] in h3/UDP? Aug 4, 2023
@mholt
Copy link
Member

mholt commented Aug 4, 2023

Thanks for the report, and for investigating -- we'll look into this soon, or anyone else is welcome to take a stab at it too.

@mholt mholt added the bug 🐞 Something isn't working label Aug 4, 2023
@Zoey2936 Zoey2936 changed the title using 0.0.0.0 and [::] as default_bind/bind results in double binding 0.0.0.0 and [::] in h3/UDP? using 0.0.0.0 and [::] as default_bind/bind results in double binding 0.0.0.0 and [::] in h3/UDP and crash? Aug 4, 2023
@Zoey2936
Copy link
Author

Zoey2936 commented Aug 4, 2023

I think with update 4, the problem should now be clear

@Zoey2936 Zoey2936 changed the title using 0.0.0.0 and [::] as default_bind/bind results in double binding 0.0.0.0 and [::] in h3/UDP and crash? using 0.0.0.0 and [::] as default_bind/bind results in double binding 0.0.0.0 and [::] in h3/UDP and crash Aug 4, 2023
@Zoey2936
Copy link
Author

Zoey2936 commented Aug 5, 2023

Can I ask what the actually wanted behaivior is? Is it wanted that 0.0.0.0 included [::]/[::] inclued 0.0.0.0, since this makes no sense to me? If I say I want to bind 0.0.0.0 then I don't want to bind [::] (and the other way, wanting to bind [::] and NOT 0.0.0.0). So will this be fixed by saying 0.0.0.0 only means IPv4 and [::] only IPv6 or will it be fixed by fixing the double binding on udp?

@francislavoie
Copy link
Member

Yeah I think that's correct, it should only bind for the same IP version as explicitly specified.

@thijsvandien
Copy link

thijsvandien commented Mar 27, 2024

The IPv6 address space does include the IPv4 address space, e.g. ::ffff:192.168.0.1. Nevertheless, it makes sense to interpret [::] as IPv6-only. 0.0.0.0 should never be considered equivalent to [::] though. Changing that means fighting Go's standard library a bit: golang/go#48723.

@mholt
Copy link
Member

mholt commented Mar 27, 2024

I'm in agreement; we can use tcp4 or tcp6 network strings accordingly. Even though ipv6 includes ipv4 address space, I don't think that's what users intend when they express a bind address that way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐞 Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants