Handling requests to IP and unused subdomains

1. Caddy version (caddy version):

v2.1.1 h1:X9k1+ehZPYYrSqBvf/ocUgdLSRIuiNiMo7CvyGUQKeA=

2. How I run Caddy:

docker

a. System environment:

  • OS: Ubuntu 20.04 LTS
  • docker version: 19.03.12

b. Command:

docker-compose up -d --force-recreate caddy

c. Service/unit/compose file:

caddy:
    image: caddy:2
    container_name: caddy
    volumes:
      - /mnt/zfsMirror/caddy/sites:/usr/share/caddy:ro
      - /mnt/zfsMirror/minecraft/BTL/plugins/dynmap/web:/var/www/dynmap:ro
      - /mnt/zfsMirror/caddy/data:/data
      - /mnt/zfsMirror/caddy/config:/config
      - /mnt/zfsMirror/caddy/logs:/var/log
      - /mnt/zfsMirror/caddy/Caddyfile:/etc/caddy/Caddyfile:ro
      - /mnt/storage/DOWNLOADS:/downloads:ro
    ports:
      - 443:443
      - 80:80
    depends_on:
      - "php-fpm"
    networks:
      - web
    restart: always

d. My complete Caddyfile or JSON config:

(logging) {
    log {
        output file /var/log/{args.0}.log {
            roll_size 1gb
            roll_keep 5
            roll_keep_for 720h
        }
    }
}

(defaults) {
    import logging main

    root * {args.0}
    templates
    file_server
}

(redirect) {
    @used {
        expression {http.request.host.labels.2} in ['joeisthebest', 'blamethelatency']
        expression {http.request.host.labels.3} in ['map', 'blog', '']
	}

	redir @used https://{host}{uri} 308
}

# redirect to https
http:// {
    import logging main

    import redirect

    redir https://joeisthebest.mooo.com{uri} 308
}

#https:// {
#    import logging main
#    
#    tls internal
#    
#    import redirect
#    
#    redir https://joeisthebest.mooo.com{uri} 308
#}

joeisthebest.mooo.com {  
    import defaults /usr/share/caddy/joeisthebest
    
    redir /downloads /downloads/
    handle /downloads/* {
        root * /

        basicauth {
            user <passwordhash>
        }

        file_server browse
    }
}

blog.joeisthebest.mooo.com {
    import logging main
    
    reverse_proxy ghost:2368

    @notAllowed {
        path /ghost/*
        not {
            remote_ip 192.168.10.0/24
        }
    }

    respond @notAllowed 403 {
        close
    }
}

blamethelatency.mooo.com {
    import defaults /usr/share/caddy/blamethelatency
}

map.blamethelatency.mooo.com {
    root * /var/www/dynmap
    
    import logging dynmap

    php_fastcgi php-fpm:9000
    file_server
}

3. The problem I’m having:

I would like to redirect requests made to IP or subdomains I am not using. The current behavior is described in list below.

  • If a request is made to https://notused.joeisthebest.mooo.com, error http: TLS handshake error from 192.168.10.1:7353: no certificate available for 'notused.joeisthebest.mooo.com' is printed to stdout.
  • If a request is made to https://50.34.48.190 the error is http: TLS handshake error from 192.168.10.1:7359: no certificate available for '172.19.0.2'
  • if a request is made to http://50.34.48.190:443/, error is http 400 Client sent an HTTP request to an HTTPS server.

Ideally the expected behavior would be as the list below (since it has to establish TLS before redirecting it should use an internal cert or one of the existing ones from letsencrypt. It’s okay if the browser does not trust the cert for the IP/hostname prior to redirect, since the redirect should take it to a hostname/cert that work):

4. Error messages and/or full log output:

{"level":"info","ts":1595965605.9427545,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":"caddyfile"}
{"level":"info","ts":1595965605.9495392,"logger":"admin","msg":"admin endpoint started","address":"tcp/localhost:2019","enforce_origin":false,"origins":["localhost:2019","[::1]:2019","127.0.0.1:2019"]}
{"level":"info","ts":1595965605.9502964,"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}
{"level":"info","ts":1595965605.9503555,"logger":"http","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
2020/07/28 19:46:45 [INFO][cache:0xc00020e6c0] Started certificate maintenance routine
{"level":"info","ts":1595965605.9574983,"logger":"http","msg":"server is listening only on the HTTP port, so no automatic HTTPS will be applied to this server","server_name":"srv1","http_port":80}
{"level":"warn","ts":1595965605.9575257,"logger":"http","msg":"user server is listening on same interface as automatic HTTP->HTTPS redirects; user-configured routes might override these redirects","server_name":"srv1","interface":"tcp/:80"}
{"level":"info","ts":1595965605.9616077,"logger":"tls","msg":"cleaned up storage units"}
{"level":"info","ts":1595965605.9617136,"logger":"http","msg":"enabling automatic TLS certificate management","domains":["map.blamethelatency.mooo.com","blog.joeisthebest.mooo.com","blamethelatency.mooo.com","joeisthebest.mooo.com"]}
{"level":"info","ts":1595965605.9756696,"msg":"autosaved config","file":"/config/caddy/autosave.json"}
{"level":"info","ts":1595965605.9756875,"msg":"serving initial configuration"}
2020/07/28 20:04:34 http: TLS handshake error from 104.236.247.64:54849: no certificate available for '172.19.0.2'
2020/07/28 20:09:00 http: TLS handshake error from 192.168.10.1:7352: no certificate available for 'notused.joeisthebest.mooo.com'
2020/07/28 20:09:00 http: TLS handshake error from 192.168.10.1:7353: no certificate available for 'notused.joeisthebest.mooo.com'
2020/07/28 20:11:25 http: TLS handshake error from 192.168.10.1:7358: no certificate available for '172.19.0.2'
2020/07/28 20:11:25 http: TLS handshake error from 192.168.10.1:7359: no certificate available for '172.19.0.2'
2020/07/28 20:20:52 http: TLS handshake error from 192.168.10.1:7383: no certificate available for '172.19.0.2'
2020/07/28 20:20:52 http: TLS handshake error from 192.168.10.1:7384: no certificate available for '172.19.0.2'

5. What I already tried:

My attempts to handle this are commented out in the caddyfile, if used it works to a point, but will overwrite my other site blocks, which is not what I want. If I use https://50.34.48.190 as the site block it does not seem to be used for requests to https://50.34.48.190/.

You can see my site block for http:// which handles requests made to http://50.34.48.190, and http://notused.joeisthebest.mooo.com for example.

I think the issue here is that https:// always superscedes the more specific site blocks. Any ideas how to prevent this, or achieve my goal in a different way?

Note, I have A records for *.joeisthebest.mooo.com and *.blamethelatency.mooo.com from freedns, which Caddy does not have a module for currently. As such requests to get a cert for *.joeisthebest.mooo.com, *.blamethelatency.mooo.com would fail. There is a certbot script for freedns that I found, at some point I may get around translating it to work for caddy.