Home Assistant, NGINX reverse proxy, and fail2ban

Hi All,

I’ve setup HA behind an NGINX reverse proxy so I can have NGINX handle SSL requests for me. This works great, but when I try to setup fail2ban to block failed login attempts, HA is seeing all clients as coming from the IP of the NGINX proxy, and not from their real IPs. I’ve added the appropriate headers to NGINX, but it looks like HA isn’t paying attention to them. Am I missing something, or should I log an issue for this?

NGINX config:

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;

    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }
    
# Home Assistant Proxy
    server {
        # Update this line to be your domain
        server_name <redacted>;
    
        # Ensure these lines point to your SSL certificate and key
        ssl_certificate /etc/nginx/certs/fullchain.pem;
        ssl_certificate_key /etc/nginx/certs/privkey.pem;
    
        # Ensure this line points to your dhparams file
        # ssl_dhparam /etc/nginx/ssl/dhparams.pem;
        
        # These shouldn't need to be changed
        listen [::]:443 default_server ipv6only=off; # if your nginx version is >= 1.9.5 you can also add the "http2" flag here
        add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
        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;
    
        proxy_buffering off;
    
        location / {
            proxy_pass http://<redacted>/;
            proxy_set_header Host $host;
            proxy_redirect http:// https://;
            proxy_http_version 1.1;
            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_set_header X-Forwarded-Host $remote_addr;
            proxy_set_header X-Real-IP $remote_addr;	
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
        }
    }
}
1 Like

By the way, these are what I meant by “the appropriate headers”:

Ok, I feel stupid now. I guess I should RTFM…

https://home-assistant.io/components/http/

A+ for detailed explanation and config :slight_smile:

did you just have to use the use_x_forwarded_for option in HTTP?

That’s correct. Just added the below to the http: section of configuration.yaml:

use_x_forwarded_for: true
1 Like

You are using the nginx on the same machine, right?

I tried to use it on different machines, but the problem is to have no access to the nginx logs.

Ah, yes, I’m using Docker and have an NGINX container and a Home Assistant container, each mapping volumes back to the host, which is how fail2ban can access the HA logs to prevent access to NGINX.

HI @sqldiablo,

I have similar configuration but not able get nginx proxy to work from last 1 week. Would you be able to help please?

The above configuration you mentioned, is that NGINX.config file?

Below is what I have in NGINX.config and then I also have hass file in “Site-deafult” folder. Please help.

NGINX.config

user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
	worker_connections 768;
	# multi_accept on;
}

http {

	##
	# Basic Settings
	##

	sendfile on;
	tcp_nopush on;
	tcp_nodelay on;
	keepalive_timeout 65;
	types_hash_max_size 2048;
	# server_tokens off;

	# server_names_hash_bucket_size 64;
	# server_name_in_redirect off;

	include /etc/nginx/mime.types;
	default_type application/octet-stream;

	##
	# SSL Settings
	##

	ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
	ssl_prefer_server_ciphers on;

	##
	# Logging Settings
	##

	access_log /var/log/nginx/access.log;
	error_log /var/log/nginx/error.log;

	##
	# Gzip Settings
	##

	gzip on;
	gzip_disable "msie6";

	# gzip_vary on;
	# gzip_proxied any;
	# gzip_comp_level 6;
	# gzip_buffers 16 8k;
	# gzip_http_version 1.1;
	# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

	##
	# Virtual Host Configs
	##

	include /etc/nginx/conf.d/*.conf;
	include /etc/nginx/sites-enabled/*;
}


#mail {
#	# See sample authentication script at:
#	# http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
# 
#	# auth_http localhost/auth.php;
#	# pop3_capabilities "TOP" "USER";
#	# imap_capabilities "IMAP4rev1" "UIDPLUS";
# 
#	server {
#		listen     localhost:110;
#		protocol   pop3;
#		proxy      on;
#	}
# 
#	server {
#		listen     localhost:143;
#		protocol   imap;
#		proxy      on;
#	}
#}

HASS file

map $http_upgrade $connection_upgrade {
default upgrade;
‘’ close;
}

server {
# Update this line to be your domain
server_name ;

# Ensure these lines point to your SSL certificate and key
ssl_certificate /home/rahul/Documents/HA/certificate.pem;
ssl_certificate_key /home/rahul/Documents/HA/privatekey.pem;
# Use these lines instead if you created a self-signed certificate
# ssl_certificate /etc/nginx/ssl/cert.pem;
# ssl_certificate_key /etc/nginx/ssl/key.pem;

# Ensure this line points to your dhparams file
ssl_dhparam /etc/nginx/ssl/dhparams.pem;


# These shouldn't need to be changed
listen [::]:443 default_server ipv6only=off; # if your nginx version is >= 1.9.5 you can also add the "http2" flag here
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
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;

proxy_buffering off;

location / {
        proxy_pass http://192.168.15.xxx:8123/;
        proxy_set_header Host $host;
        proxy_redirect http:// https://;
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Host $remote_addr;
        proxy_set_header X-Real-IP $remote_addr;	
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
}

}

Hi can you share your docker-compose entry for nginx? thank you.

Hi there, are you sure fail2ban prevent access from nginx or is it just a step after, where fail2ban bans you from Home Assistant itself… cause it seems that the proxy should still handle requests …

If you have a way of banning the IP on the whole system (ssh, nginx, http, etc… that would be fine for me !:slight_smile: