Basicauth + ip-based whitelisting

1. The problem I’m having:

I would like to reverse proxy a service (nitter) and have basicauth only when accessed from outside my network. The caddyfile that I am trying to acchieve this with is included below.

I have my router forwarding ports 443 and 80 to my docker host’s local ip and an additional dns-rewrite rule in my local dns server that redirects nitter.example.com directly to the docker host’s local ip.

No matter whether I am accessing nitter locally or externaly, basicauth is always active. I guess that the implicit “*” in the second reverse_proxy statement somehow overrules the @local part. What am I missing here? I guess there is no not_remote_ip, is there? :wink:

I am pretty confident that the overal network setup and the individual parts of the caddyfile work, and that the issue is with the combination in the caddyfile due to the following tests I did:

  • remove the local part of the caddy file
    → I am asked for a password when accessing both locally and externally
  • remove the other part of the caddy file with basicauth
    → I am not asked for a password when accessing locally and I cannot access externally at all.

2. Error messages and/or full log output:

log output not relevant here imho, will add upon request.

3. Caddy version:

v2.6.4 via docker

4. How I installed and ran Caddy:

installd via docker. The CMD inside docker is caddy run --config /etc/caddy/Caddyfile --adapter caddyfile

a. System environment:

docker runing inside a Fedora CoreOS VM on a TrueNAS Core host.

b. Command:

docker start caddy_ext

c. Service/unit/compose file:

$ docker run  \
    -v $PWD/Caddyfile:/etc/caddy/Caddyfile \
    --network=host \
    caddy:latest

d. My complete Caddy config:

Caddyfile:

nitter.example.com{
        @local {
                remote_ip forwarded 192.168.178.0/24
        }
        reverse_proxy @local http://192.168.178.111:8080

        reverse_proxy http://192.168.178.111:8080
        basicauth {
                user pw_hash
        }
}

5. Links to relevant resources:

I found this similar question here, but it was never really solved:

Your current use of @local matcher only relates to the reverse_proxy directive, but not to the basicauth directive.

However, basicauth directive also has a [matcher] argument, so you can tell the directive to only match non-local ips.

Instead of @local you could define @nonlocal:

        @nonlocal {
                not remote_ip forwarded 192.168.178.0/24
        }
1 Like

This is not safe. You’re not persisting /data, so you’re at risk of losing your certs and keys whenever you re-create the container. Make sure to review the docs on https://hub.docker.com/_/caddy

As @ypnos said, you’re only applying your matcher to the proxy and nothing else, so basicauth applies to all requests.

What you’re asking for is something more like this, i.e. always reverse_proxy but only basicauth when not local.

nitter.example.com {
	@not-local not remote_ip 192.168.178.0/24
	basicauth @not-local {
		user pw_hash
	}
	reverse_proxy 192.168.178.111:8080
}

You shouldn’t use forwarded in the remote_ip matcher, it’s not secure. We’re going to remove it in a future release.

Thank you! The hint towards the matcher for basicauth and the possibility to actually use negations nailed it!

1 Like

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