How can I secure an api endpoint from direct IP access

1. The problem I’m having:

I can reach my api using a subdomain: myapi.example.com

And I’ve secured the access of this API using a simple basicauth. My api backend is listenning to the port 8000.

Here is my Caddyfile:

myapi.example.com {
  basicauth {
    user my_hashed_password
  }
  reverse_proxy localhost:8000
}

It does work and if I try to access myapi.example.com I have to enter my username and my password. But I can still access the api using my_ip_adress:8000 and this time no authentication is recquired.

How could I also apply the basicauth settings for a direct ip access ?

2. Error message

No error message

3. Caddy version

2.6.4

4. How I installed and ran Caddy:

I installed caddy according to the caddy guide for ubuntu.

a. System environment:

Ubuntu 22.04

b. My complete Caddy config:

Caddyfile

import ./webbinding

example.com {
        root * /usr/share/caddy
        file_server
}

webbinding:

{
    acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
}

api.example.com {
  basicauth {
    user my_hashed_password
  }
  reverse_proxy localhost:8000
}

tag.example.com {
  reverse_proxy localhost:8002
}

postgresql.example.com {
  reverse_proxy localhost:5432
}

I don’t think accessing port 8000 directly involves Caddy at all since you haven’t configured Caddy to listen on port 8000. Instead, you’re connecting directly to your backend. Since the connection doesn’t involve Caddy, Caddy cannot help you there.

You should probably configure your backend to only listen on localhost by binding it to localhost:8000 or 127.0.0.1:8000 instead of listening to port 8000 on all available addresses. That way, only programs on your own machine can access it (Caddy being one of them). If your API does not have a way to configure this and you can’t change its code, configure your firewall to not allow connections to port 8000 from the outside.

If you want only Caddy to be able to access it, you could configure that using Docker: set up a bridge network, attach containers for Caddy and the API to it, update the Caddyfile to point to the service name for the API container instead of localhost, and only expose Caddy’s ports (typically 80 and 443) to the outside world.

1 Like

Indeed my api run as a docker container, so I simply changed my docker-compose file:

services:
  myapi:
    ...
    ports:
    - "127.0.0.1:8000:8000"

And it works fine now.

(Thank you ! for taking some time to explain basic things to people that are not familiar with web server and proxy things!)

1 Like

Alternatively, you could also run Caddy in Docker, and use the container names to proxy instead of localhost. That way, you wouldn’t need to bind port 8000 at all since all the traffic would happen inside your Docker network.

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