Skip to content

Blocklist not working (403 Forbidden) #425

Description

@RouL

Support guidelines

I've found a bug and checked that ...

  • ... the documentation does not mention anything about my problem
  • ... there are no open or closed issues that are related to my problem

Description

I did notice in my installation with BLOCKLIST_API_ALLOWED_IPS and BLOCKLIST_API_SECRET unset, but also with BLOCKLIST_API_ALLOWED_IPS="127.0.0.1", that entries in the blocklist where ignored. After a bit of debugging, I did see this in the log (email addresses changed):

addy           | 172.20.0.1 - - [06/Jul/2026:19:50:41 +0000] "GET /api/blocklist-check?recipient=ttt%40ttt.de&from_email=zzz%40zzz.com HTTP/1.1" 403 52 "-" "rspamd-3.14.0"

The 403 makes sense, since of course that IP is NOT in the list. After a bit of digging, I did find this line:

local blocklist_api_url = '${APP_URL}/api/blocklist-check'

(https://github.com/anonaddy/docker/blob/master/rootfs/etc/cont-init.d/14-config-rspamd.sh#L246)

In my opinion, this should look like this, so it does connect via 127.0.0.1:

local blocklist_api_url = 'http://127.0.0.1:8000/api/blocklist-check'

Especially in Docker you can't even really count on the IP always being the same, so it would make sense to just use localhost. This also makes sure, the request does not have to make the unneccessary roundtrip over an external reverse proxy with SSL handshake, etc.

Expected behaviour

The API call to the blocklist-check runs on localhost.

Actual behaviour

The API call to the blocklist-check is using the external URL (env API_URL).

Steps to reproduce

  1. Add a domain or e-mail to the blocklist
  2. Add an alias
  3. send an e-mail from the blocked address to the alias
  4. check logs

Docker info

Client: Docker Engine - Community
 Version:    29.6.1
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc.)
    Version:  v0.35.0
    Path:     /usr/libexec/docker/cli-plugins/docker-buildx
  compose: Docker Compose (Docker Inc.)
    Version:  v5.3.0
    Path:     /usr/libexec/docker/cli-plugins/docker-compose

Server:
 Containers: 11
  Running: 11
  Paused: 0
  Stopped: 0
 Images: 10
 Server Version: 29.6.1
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Using metacopy: false
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: systemd
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
 CDI spec directories:
  /etc/cdi
  /var/run/cdi
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: e53c7c1516c3b2bff98eb76f1f4117477e6f4e66
 runc version: v1.3.6-0-g491b69ba
 init version: de40ad0
 Security Options:
  apparmor
  seccomp
   Profile: builtin
  cgroupns
 Kernel Version: 6.8.0-134-generic
 Operating System: Ubuntu 24.04.4 LTS
 OSType: linux
 Architecture: x86_64
 CPUs: 2
 Total Memory: 3.73GiB
 Name: midgard
 ID: d3086ab3-0e94-468c-a07a-f7832a80a03a
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Experimental: false
 Insecure Registries:
  ::1/128
  127.0.0.0/8
 Live Restore Enabled: false
 Firewall Backend: iptables
  EnableUserlandProxy: true
  UserlandProxyPath: /usr/bin/docker-proxy

Docker Compose config

name: anonaddy
services:
  acme:
    build:
      context: /srv/docker/anonaddy/acme
      dockerfile: Dockerfile
    command:
      - daemon
    container_name: addy_acme
    environment:
      HETZNER_TOKEN: <CENSORED>
    networks:
      default: null
    restart: unless-stopped
    volumes:
      - type: volume
        source: acme_data
        target: /acme.sh
      - type: volume
        source: certs
        target: /certs
      - type: bind
        source: /var/run/docker.sock
        target: /var/run/docker.sock
  addy:
    container_name: addy
    depends_on:
      acme:
        condition: service_started
        restart: true
        required: true
      database:
        condition: service_healthy
        restart: true
        required: true
      redis:
        condition: service_started
        restart: true
        required: true
    environment:
      ANONADDY_BANDWIDTH_LIMIT: "209715200"
      ANONADDY_DKIM_SELECTOR: zaddy
      ANONADDY_DKIM_SIGNING_KEY: /data/dkim/<CENSORED>.private
      ANONADDY_DOMAIN: <CENSORED>
      ANONADDY_ENABLE_REGISTRATION: "false"
      ANONADDY_HOSTNAME: mx.<CENSORED>
      ANONADDY_NEW_ALIAS_LIMIT: "60"
      ANONADDY_SECRET: <CENSORED>
      ANONADDY_SIGNING_KEY_FINGERPRINT: ""
      APP_KEY: base64:<CENSORED>
      APP_NAME: <CENSORED>
      APP_URL: https://<CENSORED>
      BLOCKLIST_API_ALLOWED_IPS: 127.0.0.1
      DB_DATABASE: addy
      DB_HOST: addy_database
      DB_PASSWORD: <CENSORED>
      DB_USERNAME: addy
      LOG_IP_VAR: http_x_forwarded_for
      MAIL_FROM_NAME: <CENSORED>
      POSTFIX_SMTP_TLS: may
      POSTFIX_SMTPD_TLS: may
      POSTFIX_SMTPD_TLS_CERT_FILE: /certs/tls.crt
      POSTFIX_SMTPD_TLS_KEY_FILE: /certs/tls.key
      POSTFIX_SPAMHAUS_DQS_KEY: <CENSORED>
      REAL_IP_FROM: 172.20.0.0/16
      REDIS_HOST: addy_redis
      RSPAMD_ENABLE: "true"
      RSPAMD_WEB_PASSWORD: <CENSORED>
    image: anonaddy/anonaddy:latest
    labels:
      traefik.enable: "true"
      traefik.http.middlewares.redirect-https.redirectScheme.permanent: "true"
      traefik.http.middlewares.redirect-https.redirectScheme.scheme: https
      traefik.http.routers.anonaddy-http.entrypoints: web
      traefik.http.routers.anonaddy-http.middlewares: redirect-https
      traefik.http.routers.anonaddy-http.rule: Host(`<CENSORED>`)
      traefik.http.routers.anonaddy-http.service: anonaddy
      traefik.http.routers.anonaddy-https.entrypoints: websecure
      traefik.http.routers.anonaddy-https.rule: Host(`<CENSORED>`)
      traefik.http.routers.anonaddy-https.service: anonaddy
      traefik.http.routers.anonaddy-https.tls: "true"
      traefik.http.routers.anonaddy-https.tls.certresolver: letsencrypt
      traefik.http.routers.anonaddy-rspamd-http.entrypoints: web
      traefik.http.routers.anonaddy-rspamd-http.middlewares: redirect-https
      traefik.http.routers.anonaddy-rspamd-http.rule: Host(`<CENSORED>.<CENSORED>`)
      traefik.http.routers.anonaddy-rspamd-http.service: anonaddy-rspamd
      traefik.http.routers.anonaddy-rspamd-https.entrypoints: websecure
      traefik.http.routers.anonaddy-rspamd-https.rule: Host(`<CENSORED>.<CENSORED>`)
      traefik.http.routers.anonaddy-rspamd-https.service: anonaddy-rspamd
      traefik.http.routers.anonaddy-rspamd-https.tls: "true"
      traefik.http.routers.anonaddy-rspamd-https.tls.certresolver: letsencrypt
      traefik.http.services.anonaddy-rspamd.loadbalancer.server.port: "11334"
      traefik.http.services.anonaddy.loadbalancer.server.port: "8000"
    networks:
      default: null
      traefik: null
    ports:
      - mode: ingress
        target: 25
        published: "25"
        protocol: tcp
    restart: unless-stopped
    volumes:
      - type: volume
        source: addy_data
        target: /data
      - type: volume
        source: certs
        target: /certs
        read_only: true
  database:
    container_name: addy_database
    environment:
      MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: "1"
      MARIADB_AUTO_UPGRADE: "1"
      MARIADB_DATABASE: addy
      MARIADB_ROOT_PASSWORD: <CENSORED>
    healthcheck:
      test:
        - CMD
        - healthcheck.sh
        - --connect
        - --innodb_initialized
      timeout: 5s
      interval: 10s
      retries: 3
      start_period: 10s
    image: mariadb:latest
    networks:
      default: null
    read_only: true
    restart: unless-stopped
    volumes:
      - type: volume
        source: mariadb_data
        target: /var/lib/mysql
      - type: tmpfs
        target: /tmp
      - type: tmpfs
        target: /run/mysqld
  redis:
    container_name: addy_redis
    image: redis:8-alpine
    networks:
      default: null
    restart: unless-stopped
networks:
  default:
    name: anonaddy_default
  traefik:
    name: traefik
    external: true
volumes:
  acme_data:
    name: anonaddy_acme_data
  addy_data:
    name: anonaddy_addy_data
  certs:
    name: anonaddy_certs
  mariadb_data:
    name: anonaddy_mariadb_data

Logs

addy           | 172.20.0.1 - - [06/Jul/2026:19:50:41 +0000] "GET /api/blocklist-check?recipient=ttt%40ttt.de&from_email=zzz%40zzz.com HTTP/1.1" 403 52 "-" "rspamd-3.14.0"

Additional info

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions