Ban by subnet in http component (with working code)

I’ve been plagued by hackers trying to log in to my Home Assistant.
I added each offender to ip_bans.yaml but they just increment their ip address to get around the ban.

I’ve changed the http component to be able to ban by subnet (a.b.c.d/n etc) and this has eased the problem considerably.

My fork is here

Would anybody find this useful?

To test my forked http component:
Make sure your HA version is at least 2025.2.5
Copy the whole http component from my fork into the custom_components config folder.
You have to add a "version": "1.0.0" at the bottom of manifest.json so it looks like this

{
  "domain": "http",
  "name": "HTTP",
  "codeowners": ["@home-assistant/core"],
  "documentation": "https://www.home-assistant.io/integrations/http",
  "integration_type": "system",
  "iot_class": "local_push",
  "quality_scale": "internal",
  "version": "1.0.0"
}

To ban networks, add the following to configuration.yaml in the http section

http:
  ....
  ip_ban_enabled: True # optional as defaults to True
  banned_networks: # Make sure the format is right, e.g. /16 must end in 0.0/16
    - 111.7.0.0/16
    - 45.0.0.0/8
    - 179.43.0.0/16
    - 123.160.0.0/14
    - 195.178.0.0/16
  log_banned_networks: True # optional as defaults to True
  notify_banned_networks: True # optional as defaults to True

If you enable logging it will report as info messages so if the default logger setting is above this you will need to add a log line to the logger on configuration.yaml like this

logger:
  default: critical
  logs:
    custom_components.http: info

I strongly suggest you install samba so you can access the config folder without using the ha file editor addon in case something breaks and you are locked out of ha. You should also have ssh access through a client like putty so you can restart if needed.

Views please
[modified from original as configuration is now in configuration.yaml]

3 Likes

Yeah, been getting daily attempts lately. It would be great if this option to ban entire subnets were made part of core functionality because having to fork a component means you’d have to take responsibility for keeping it up to date.

Not sure why this option hasn’t made it into core. Just add checks that you cannot ban internal IP ranges so that you don’t get locked out and it should be safe for general use.

Good point - I’ll look into this. I think I can get it from get_supervisor_ip in homeassistant.helpers.hassio

If I get traction here I’ll look into tidying up the configuration.
ATM it’s in network_bans.yaml but should be in configuration.yaml as it’s only accessed at load time.

I know how to generate schemas for configuration.yaml but I don’t know how to retrieve the configuration settings from the hass (HomeAssistant) object - any pointers?

Again, if it gets traction I’ll then look to a pull request so it’s incorporated into the ha core.

1 Like

Can’t help with pointers beyond reiterating the obvious - throw “not allowed” error on any subnet which starts in 10.0.0.0/8-32, 172.16.0.0/12-32 or 192.168.0.0/24-32. Hell, I’d simply throw an error if the subnet you’re covering might potentially cover anything starting in 10, 172 or 192 out of a sheer abundance of caution.

I seem to recall this was already proposed as a PR and rejected by the almighty powers, but I have no concrete links to back it up. Maybe with the internal IP safeguards in place, this might be more acceptable.

If you do get a PR raised, please link it in this thread. There are plenty of people who would back this request, both from a regular user perspective as well as from the people who created the whitelist option PR 3 times unsuccessfully.

Please note the changes in my first post as the configuration has changed.
The banned networks are now in configuration.yaml to be more conststent.
You no longer need the extra file banned_networks.yaml

Installed and tested.

I had the same experience: IP addresses from 145.148.10.0/24 testing loggi to HA daily and incrementing their IPs after being banned.

Banning the whole subnet helps.

I hope this will make its way into HA core.

Thanks for the support.

I’ve modified the security filter just now.
When logging unsafe requests the log didn’t show the offending source url, just the path.
It does now.

I also added the log message as a persistent notification because it’s easy to miss the attempted hacks if you don’t regularly read the logs.

A typical log entry/notification now looks like

2025-03-10 13:33:20.585 WARNING (MainThread) [custom_components.http.security_filter] Filtered a potential harmful request from 172.17.0.1 to: /cgi-bin/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/bin/sh

Note this is a separate issue to network bans - it just makes it easier to identify hackers

I think I’m getting close to a pull request.
I’m away for a few days so I’ll do that at the end of the week unless something else crops up.

1 Like

One more thing you might want to look into before submitting the PR.

How are you handling overlapping network entries Eg. 1.2.3.4/32 & 1.2.3.0/24?

The current config checker will throw an error if it finds a duplicate IP. Do you need to guard against this scenario?

Not sure I do.
Why does it matter?
My “new” logic logic iterates each network given in the config and checks for if caller in network.
It will react to the first one found.

I could check at load time for every combination of network if a overlaps b but it seems overkill.
Am I missing something?

Logging the blocks has raised an interesting conundrum.
HA logged repeated attempts to probe with unsafe characters/potentially harmful requests from a user in network 45.156.128.0/24 so I blocked the complete range of the server.
It turns out that the server belongs to internet-census.org in the USA which describes itself as benignly scanning the internet for security weaknesses for benchmarks and yet the ICANN d/b shows the ip as an individual registrant.
I don’t like the thought of this probing in case they actually find a weakness in HA and crash it (or worse).
Should we block these?

My main concern is that currently ipbans throws a configuration error if you enter the same IP address twice. My comment was more of a heads up to ensure the same thing does not occur if you enter overlapping ranges.

If your code is only reacting to the first one found and handles the block gracefully without errors, then that’s even better.

I say treat it just like any other non-private IP and let the user decide whether they’re comfortable being probed.

Update
I want to add an optional description for each banned network in the config so the user can remind themselves in the persistent notification and log entry why they banned network if they want to.

Something like the current ban message followed by the (optional) description in quotes at the end…

2025-03-13 15:06:05.605 WARNING (MainThread) [custom_components.http.ban] Prevented access attempt from customer.sharktech.net (45.58.159.161) which is in banned network 45.0.0.0/8 “Banned whole subnet not just 45.58.128.0 - 45.58.191.255 because I like sledghammers!”

I plan to do the pr next week all being well.

PR created Improve http component to ban IP addresses by subnet #140661

It’s my first so I’m going to need help getting it through

1 Like

Left you a like on the PR, since that’s basically all I can contribute at this point.

Quick question though - any particular reason why the banned_networks need to go in the configuration.yaml file instead of the existing ip_bans.yaml file?

Thanks for the like.

For individual IP bans:
ip_bans.yaml is a dynamic file updated at runtime by the ban s/w (failed logins > threshold creates an entry).
It is only read at load load time.
New bans are written when they occur (ready for the next restart) and all the banned IPs are stored in the component.

For subnet bans:
These are not updated dynamically - only when the user adds them.
The banned networks list in configuration.yaml is loaded at boot time and is fixed until the user updates it and restarts HA - just like any other component.
I thought it best to keep static configuration away from dynamic component updates - which is possibly what the developer of the individual IP ban s/w thought hence creating ip_bans.yaml.

Long term if this pr gets adopted it would be good to have a button on the developer page to reload http so new subnet bans could be loaded without a restart…

Thanks, that clears it up!

I definitely need this feature <3 I’ve created a feature request exactly for this one, but didn’t thought to check if someone already developed something in another channel.
Thank you so much for your hard work and I really hope it’ll part of one of the next releases

The documentation PR is at Documentation update for HA PR #140661 (http banned networks) #38012