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

Automatic HTTP redirect not working if domain block has another value for bind #4738

Closed
Xinayder opened this issue Apr 27, 2022 · 12 comments
Closed
Labels
question ❔ Help is being requested

Comments

@Xinayder
Copy link

After recently updating my Caddy from 2.4.3 to the latest version and restarting the daemon, I kept getting an error in my log:

Apr 27 20:58:11 yggdrasil caddy[785913]: {"level":"info","ts":1651093091.29062,"logger":"http","msg":"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}

Apr 27 20:58:11 yggdrasil caddy[785913]: {"level":"info","ts":1651093091.2908275,"logger":"http","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}

Apr 27 20:58:11 yggdrasil caddy[785913]: run: loading initial config: loading new config: loading http app module: provision http: srv0: invalid listener address: :0

I thought I had been missing any directives or something else that was removed/deprecated, however I couldn't find anything related to this everywhere else.

I tried setting global options, explicitly enabling automatic HTTPS redirects, but none of that worked. By running caddy adapt on my Caddyfile I found out that it only had HTTPS listeners and no HTTP listeners. Then I found out that the default value for the bind is to bind to all available interfaces, and upon removing the directive from my domain block, the error was gone.

Caddyfile for reference:

# The Caddyfile is an easy way to configure your Caddy web server.
#
# Unless the file starts with a global options block, the first
# uncommented line is always the address of your site.
#
# To use your own domain name (with automatic HTTPS), first make
# sure your domain's A/AAAA DNS records are properly pointed to
# this machine's public IP, then replace the line below with your
# domain name.

(_unauthorized) {
        error {args.0} "Unauthorized" 403
}

*.mydomain.com, mydomain.com {
        #    bind 127.0.0.1
        bind 127.0.0.1 ::1

        header {
                # disable FLoC tracking
                Permissions-Policy interest-cohort=()

                # enable HSTS
                Strict-Transport-Security max-age=31536000;

                # disable clients from sniffing the media type
                X-Content-Type-Options nosniff

                # clickjacking protection
                X-Frame-Options DENY

                # keep referrer data off of HTTP connections
                Referrer-Policy no-referrer
        }

        tls cert@mydomain.com {
                dns vultr REDACTED
        }

        # Set this path to your site's directory.
        root * /var/www/mydomain.com
        file_server {
                hide blog tags categories
        }

        handle_errors {
                rewrite * /error.html
                templates
                file_server
        }

        @resume {
                header User-Agent *curl*
                path /
        }

        rewrite @resume /resume.json

        # Another common task is to set up a reverse proxy:
        # reverse_proxy localhost:8080

        # Or serve a PHP site through php-fpm:
        # php_fastcgi localhost:9000

        # Refer to the Caddy docs for more information:
        # https://caddyserver.com/docs/caddyfile
}
@francislavoie
Copy link
Member

The bind address ::1 is not the right thing to use for IPv6, you should use [::1] instead.

In case you got that from the docs, there was a mistake and it was fixed in caddyserver/website#227.

@francislavoie francislavoie added the question ❔ Help is being requested label Apr 27, 2022
@Xinayder
Copy link
Author

Does this also apply for IPv6 addresses too other than localhost; they should be wrapped in brackets?

@francislavoie
Copy link
Member

francislavoie commented Apr 27, 2022

Yes, because otherwise the IPv6 colons conflict with the colon for the port number.

For example, when you run caddy adapt to convert your Caddyfile to JSON (which Caddy does itself at startup), then the bind addresses look like this:

"listen": [
	"127.0.0.1:443",
	"::1:443"
],

You can pretty clearly see where parsing can go wrong there -- the error saying :0 is because it looks at the first 0 and gets an empty string after it, and an empty string gets converted to the integer 0.

So with square brackets:

"listen": [
	"127.0.0.1:443",
	"[::1]:443"
],

This makes more sense from a parsing perspective.

@Xinayder
Copy link
Author

Ah, thank you very much! This went unnoticed when I was trying to debug an IPv6 issue in my server.

@Cnly
Copy link

Cnly commented Apr 28, 2022

I ran into a similar problem with binding IPv6 addresses after upgrading to 2.5.0. The error message is very unclear. It used to work on and before 2.4.6 so I think this is a regression that should be fixed, instead of just changing the docs.

@francislavoie
Copy link
Member

This was an intended change. See #4532

I agree that the error message is misleading and unclear, though. I'll see if I can improve it to have a "did you mean" in there to suggest using brackets if there's more than one : in the string.

@francislavoie
Copy link
Member

francislavoie commented Apr 28, 2022

#4740 should improve it.

My earlier analysis that :0 was from empty string to int conversion or w/e was incorrect, the error handling logic was using a clobbered value instead. Whoops. That's fixed too, for future users.

@Xinayder
Copy link
Author

Would it be possible to add a functionality to caddy fmt to automatically add brackets to a IPv6 address? I think it's not that difficult, just detect an IP with colons and hexadecimal numbers with more than 4 parts and escape it?

@mholt
Copy link
Member

mholt commented Apr 29, 2022

That's probably possible.

Actually I'm kind of surprised the brackets are needed when there's no port. Is it normal to write IPv6 addresses with brackets even without ports?

@francislavoie
Copy link
Member

@mholt in this case, there is a port, cause this is for listener addresses and :443 gets suffixed

@mholt
Copy link
Member

mholt commented Apr 29, 2022

@francislavoie Ah true... but I mean, shouldn't JoinHostPort do that for us? Or maybe we should wrap it for the user. I dunno.

Ah, RFC 7239 section 6.1 says:

Also, note that an IPv6 address is always enclosed in square brackets.

So, there we have it. I guess the square brackets need to be provided by the user.

Yeah, updating our docs should be fine then.

@francislavoie
Copy link
Member

Yeah, updating our docs should be fine then.

Already done 😅 caddyserver/website#227

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question ❔ Help is being requested
Projects
None yet
Development

No branches or pull requests

4 participants