Not getting user's IP address

I am using Cloudflare tunnel to host my VW instance from my house to bypass CGNAT, but I am having issues with incorrect IP address being logged, hence, my fail2ban won’t work. Instead of the user’s actual IP address, I am getting the IP address of my VW docker container. I already tried adding the env var of IP_HEADER, and set it to either X-Forwarded-For, X-Real-IP, or CF-Connecting-IP but all these still logs my container’s IP address. I am not sure what I am missing here, would highly appreciate if someone could provide their thoughts.

Could you share your docker compose file?
(Don’t forget to remove any confidencial information)

Here’s my docker-compose.yml file

I already removed the IP_HEADER as it doesn’t seem to work.

services:
  vaultwarden:
    container_name: vaultwarden
    user: 1000:1000
    image: vaultwarden/server:latest
    environment:
      - WEBSOCKET_ENABLED=true
      - LOG_LEVEL=info
      - LOG_FILE=/data/log/vaultwarden.log
      - LOGIN_RATELIMIT_SECONDS=120
      - LOGIN_RATELIMIT_MAX_BURST=5
      - ADMIN_RATELIMIT_SECONDS=300
      - SIGNUPS_ALLOWED=false
      - ADMIN_TOKEN=
      - DOMAIN=
    volumes:
      - ./data:/data
      - ./log:/data/log
    ports:
      - 4000:80
    restart: always

Did you check at the Administration site (https://mydomian.com/admin), if you are not overwriting this setting?
Also, did you checked at the .env the same?

Yes, everything is the same. Previously when my instance was still in a VPS, everything works just fine, I think the issue lies in the connection between Cloudflare tunnel and the vaultwarden container, maybe some config is required which I have no any other idea.

For your reference, here is my docker-compose.yml for Cloudflare tunnel:

services:
  cloudflare_tunnel:
    container_name: cloudflare_tunnel
    image: cloudflare/cloudflared:latest
    restart: unless-stopped
    environment:
      - TUNNEL_TOKEN=xxxxx
    command: tunnel --no-autoupdate run
    networks:
      - exposed

networks:
  exposed:
    external: false
    ipam:
      driver: default
      config:
        - subnet: "172.10.0.0/16"
          gateway: "172.10.0.1"

And this is my docker-compose.yml for Vaultwarden:

services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    command: "/start.sh"
    restart: unless-stopped
    environment:
      ROCKET_PROFILE: "release"
      ROCKET_ADDRESS: "0.0.0.0"
      ROCKET_PORT: "80"
      DEBIAN_FRONTEND: "noninteractive"
      SEND_PURGE_SCHEDULE: "0 0 5 31 2 ?"
      TRASH_PURGE_SCHEDULE: "0 0 5 31 2 ?"
      PUSH_ENABLED: "true"
      PUSH_INSTALLATION_ID: "xxxx"
      PUSH_INSTALLATION_KEY: "xxxxx"
      DOMAIN: "https://server.com/"
      USER_ATTACHMENT_LIMIT: "1000000"
      SMTP_HOST: "smtp.server.com"
      SMTP_SECURITY: "starttls"
      SMTP_PORT: "465"
      SMTP_FROM: "user@server.com"
      SMTP_USERNAME: "user@server.com"
      SMTP_PASSWORD: "xxxxxx"
      SIGNUPS_ALLOWED: "false"
      IP_HEADER: "X-Forwarded-For"
    networks:
      - cloudflare_tunnel
    volumes:
      - type: bind
        source: /data
        target: /data
        read_only: false

networks:
  cloudflare_tunnel:
    name: cloudflare_tunnel_exposed
    external: true

Take a look and compare your implementation.

Interesting, thank you for this, I am running cloudflare natively on my linux machine, I’ll try yours and see how it will go if I move it to docker.

I asked Perplexity AI about this. It told me that Fail2ban reads log files, it doesn’t act as a firewall. It gave me some configurations for Nginx, Vaultwarden, and Fail2ban to set this up, adding rules to the CloudFlare firewall rather than a local firewall. Suggest you put your question into Perplexity / ChatGPT and it should help with configuration.

Here’s a suggested prompt: “I run vaultwarden on on my linux instance with an Nginx reverse proxy. I have a cloudflare tunnel for access from the internet. I use fail2ban to protect my instance. How do ensure fail2ban has client IPs from the internet”.

Upon checking further, it turns out that it was a mistake from my end, I rarely login to my Admin page, but I checked on it again and the setting for IP_HEADER was set to X-Real-IP and whatever I do in my compose file’s env var, it won’t override it. So, after changing the value to X-Forwarded-For in the admin page, it is now working, and I am getting the correct user’s IP address. I am now able to use fail2ban which calls a cloudflare API that will create a rule to block an IP.

Thank you, @juanbretti for your effort to help, cheers!

1 Like