Home Assistant bans docker IP instead of remote client IP

I am running HA in docker (network_mode: “host”) and few other application along with NGINX reverse proxy. When remote client tries to access HA with wrong password after 5 tries HA blocks my docker IP 172.18.0.5 which belongs to NGINX rather than remote client IP.
I think I have proper proxy_set_headers in place along with http component in HA config as well and I couldn’t figure it out so looking for some advice please.
My Google Assistant and remote access works as expected.

Here is my HA config:

http:
  api_password: !secret api_password
  ip_ban_enabled: True
  login_attempts_threshold: 5
  base_url: https://mysubdomain.domain.org
  use_x_forwarded_for: true
  trusted_proxies: 127.0.0.1
  trusted_networks: 192.168.1.0/24

and NGINX config:

load_module /usr/lib/nginx/modules/ngx_http_geoip_module.so;
load_module /usr/lib/nginx/modules/ngx_stream_geoip_module.so;

error_log  /etc/nginx/logs/error.log warn;

events {
  worker_connections  4096;
}

http {
    geoip_country   /etc/nginx/GeoIP/GeoIP.dat;
    geoip_city      /etc/nginx/GeoIP/GeoLiteCity.dat;

    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }
    
    map $geoip_country_code $allowed_country {
        default no;
        US yes;
    }
    
    geo $exclusions {
        default 0;
        192.168.1.0/24 1;
    }

    log_format main  '$time_local exclusion:$exclusions allowed_country:$allowed_country country_code:$geoip_country_code http_status:$status ip_address:$remote_addr bytes_sent:$body_bytes_sent country_name:"$geoip_country_name" "$http_referer" "$request" "$http_user_agent" "$gzip_ratio"';
    
    server {
        if ($allowed_country = yes) {
          set $exclusions 1;
        }
        if ($exclusions = "0") {
          return 444;
        }
        
        listen                443 ssl;
        server_name           mysubdomain.domain.org;
        
        ssl_certificate       /etc/letsencrypt/live/mysubdomain.domain.org/fullchain.pem;
        ssl_certificate_key   /etc/letsencrypt/live/mysubdomain.domain.org/privkey.pem;
        
        ssl on;
        ssl_protocols         TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers           "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
        ssl_prefer_server_ciphers on;
        ssl_session_cache shared:SSL:10m;
        
        access_log            syslog:server=192.168.1.250:5143,severity=info main;
        
        add_header            Strict-Transport-Security "max-age=31536000; includeSubdomains";
        proxy_buffering       off;
        proxy_set_header      Host $host;
        proxy_set_header      X-Real-IP $remote_addr;
        proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header      Upgrade $http_upgrade;
        proxy_set_header      Connection $connection_upgrade;
        proxy_http_version    1.1;
        
        location / {
          proxy_pass          http://192.168.1.250:8123/;
          proxy_set_header    Host $host;
          proxy_redirect      http:// https://;
          proxy_http_version  1.1;
          proxy_set_header    X-Real-IP $remote_addr;
          proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header    Upgrade $http_upgrade;
          proxy_set_header    Connection $connection_upgrade;
        }

        location /api/websocket {
          proxy_pass          http://192.168.1.250:8123/api/websocket;
          proxy_set_header    Host $host;
          proxy_redirect      http:// https://;
          proxy_http_version  1.1;
          proxy_set_header    X-Real-IP $remote_addr;
          proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header    Upgrade $http_upgrade;
          proxy_set_header    Connection $connection_upgrade;
        }
    }
}
1 Like

If you are using NGINX on 172.18.0.5, why do you have trusted proxy set as 127.0.0.1?

Edit, I use caddy, but my X-Forwarded-For header setting is set for $remote_addr, not $proxy_add_x_forwarded_for

1 Like

Thanks a lot.
Looks like trusted proxy setting to my Docker NGINX IP did the trick, now I see the real IP from the client.
By the way I have not changed the X-Forwarded-For and still it worked.
Let me learn now how to make sure in case if I upgrade NGINX still it gets same IP.
Appreciate it.
Thank you

Are you able to share how you get the real IP to show up in the HA log?

I’m using the NGINX hassIO addon and it always shows a 172...* address

Not sure I understood the question correct but this is how it shows up in the log file.

WARNING (MainThread) [homeassistant.components.http.ban] Login attempt or request with invalid authentication from xxx.xxx.xxx.xxx

I’d be glad to know what was the change you made to make HA understand the real IP of the request origin

If I remember correctly this what I did.
For http component added following two lines:

    use_x_forwarded_for: true
    trusted_proxies: <NGINX IP address here, or 127.0.0.1 if hosted on the same machine>

I think I followed guide from here:

Hope this helps