Clear Banned LAN IPs

Hostname hassio
System HassOS 2.12
Deployment production
(Raspberry PI 3 B)

In testing API calls, I got my PC banned as indicated via some log messages.
Of course I searched posts for the location of this banned_ip file, but none of the posts had relevant info.

How do I clear my banned LAN IP, and how do I trust my LAN to avoid this issue.
BTW- Not using SSL

4 Likes

You would have an ip_bans.yaml in your configuration directory. Delete that and restart HA.

More info: https://www.home-assistant.io/integrations/http/#ip-filtering-and-banning

(edit: changed link to http integration docs)

18 Likes

Yes, I had seen that info in another post. I do not have such a file. I looked via the GUI’s “Configurator” and also with WinSCP, showing hidden files. Even performed a search with WinSCP using *ip* on the root, and no relevant matches.
Thanks for the answer though.

Any input on how to configure the ban parameters? IE setting attempt thresholds and trusted IPs or subnets?

That information is on the same page I linked. What is your http: configuration?

My oversight. The page you linked is actually a different than I thought it was. It does indeed answer my question about parameters. To answer your question, I actually did not have any http configurations in the configuration.yaml. I’m going through the page now to learn and set it up correctly. For anyone else reading, note the page indicates trusted_networks paramter is deprecated since 0.89 release. Configuration moved to Trusted Networks auth provider.

My Hass.io just updated recently to version 94.4 (or maybe .5)

Just an update to anyone following, I never did find a ip_bans.yaml file, but that may have been due to a view not refreshing or something. Adding the trusted_networks parameter to the configuration.yaml file and rebooting appears to have alleviated my ban issue.
Now my API calls are getting “405 Method Not Allowed”, but I’m sure that is another topic.
Thanks for the assist.

1 Like

Automated Script to Unban Your Own IP from Home Assistant

I’ve been dealing with the same frustration of getting banned from my own Home Assistant server. Created a script that automatically detects and removes only your IP from the ban list, leaving other bans intact.

Features:

  • Auto-detects your current LAN IP
  • Only removes YOUR IP (preserves other bans)
  • Creates backups before modifying
  • Automatically restarts HA Core
  • Works on macOS/Linux

Shell Script: ssh-unblock-me.sh

./ssh-unblock-me.sh
# Detected local IP: 192.168.50.100
# Found ban entry, removing...
# HA Core restarting...

Bonus: Also created an AppleScript version that can be saved as a macOS app and added to your Dock for one-click unbanning!

The script properly removes both the IP entry and its associated timestamp, leaving a clean ip_bans.yaml file. No more manual SSH editing or deleting the entire ban list.

Hope this helps others who keep getting locked out of their own HA instance! :unlock:

1 Like

Many thanks for this, I just used this to create a quick custom component and use folder watcher to monitor if ip_bans.yaml changes and then runs to clear configured IPs (127.0.0.1 and Home assistants IP for me)

2 Likes

Hello Holdestmade!

Could you please help us with the custom component you created?
I’m experiencing the same issue and constantly have to clear this file!

Thank you very much in advance!

Sure, you also need to setup folder watcher to watch ipbans.yaml and add the automation at the end

custom_components/unban_local/init.py

import logging
import os

from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.helpers.typing import ConfigType

from .const import DOMAIN

_LOGGER = logging.getLogger(__name__)

PLATFORMS = []

async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
    hass.data.setdefault(DOMAIN, {})
    
    ip_string = entry.data.get("banned_ips", "")
    ips_to_unban = [ip.strip() for ip in ip_string.split(',') if ip.strip()]
    
    hass.data[DOMAIN]["ips_to_unban"] = ips_to_unban
    _LOGGER.info("Monitoring the following IPs for unbanning: %s", ips_to_unban)

    ip_bans_file = hass.config.path("ip_bans.yaml")

    async def handle_clear_local_bans(call: ServiceCall) -> None:
        ips_to_check = hass.data[DOMAIN].get("ips_to_unban", [])
        if not ips_to_check:
            _LOGGER.warning("No IPs configured for unbanning.")
            return

        _LOGGER.info("Running local IP unban check...")

        if not os.path.exists(ip_bans_file):
            _LOGGER.debug("ip_bans.yaml does not exist. No action needed.")
            return

        try:
            with open(ip_bans_file, "r", encoding="utf-8") as f:
                lines = f.readlines()

            unbanned_lines = []
            ip_was_removed = False
            skip_next_line = False

            for i, line in enumerate(lines):
                if skip_next_line:
                    skip_next_line = False
                    continue
                
                line_stripped = line.strip()
                triggered = False
                for ip in ips_to_check:
                    ip_to_find = f"{ip}:"
                    if line_stripped.startswith(ip_to_find):
                        ip_was_removed = True
                        triggered = True
                        if (i + 1 < len(lines)) and "banned_at:" in lines[i+1]:
                            skip_next_line = True
                        break

                if not triggered:
                    unbanned_lines.append(line)

            if ip_was_removed:
                _LOGGER.info("Found and removed a local IP ban. Updating ip_bans.yaml.")
                with open(ip_bans_file, "w", encoding="utf-8") as f:
                    f.writelines(unbanned_lines)
            else:
                _LOGGER.info("No configured IPs were found in the ban list.")

        except Exception as e:
            _LOGGER.error("Error while processing ip_bans.yaml: %s", e)

    hass.services.async_register(DOMAIN, "clear_bans", handle_clear_local_bans)

    return True


async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
    hass.services.async_remove(DOMAIN, "clear_bans")
    
    if DOMAIN in hass.data:
        hass.data.pop(DOMAIN)
        
    _LOGGER.info("Successfully unloaded Local IP Unbanner.")
    return True

custom_components/unban_local/config_flow.py

import logging
import socket
import voluptuous as vol

from homeassistant import config_entries
from .const import DOMAIN

_LOGGER = logging.getLogger(__name__)


def _get_local_ips():
    ips = {"127.0.0.1"}
    s = None
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.settimeout(0)
        s.connect(("8.8.8.8", 80))
        lan_ip = s.getsockname()[0]
        if lan_ip:
            ips.add(lan_ip)
    except Exception as e:
        _LOGGER.warning("Could not auto-detect LAN IP address, please enter manually: %s", e)
    finally:
        if s:
            s.close()
    return ips


class UnbanLocalConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):

    VERSION = 1

    async def async_step_user(self, user_input=None):
        if self._async_current_entries():
            return self.async_abort(reason="single_instance_allowed")

        if user_input is not None:
            return self.async_create_entry(title="Local IP Unbanner", data=user_input)

        try:
            detected_ips = await self.hass.async_add_executor_job(_get_local_ips)
            suggested_ips = ", ".join(sorted(list(detected_ips)))
        except Exception as e:
            _LOGGER.warning("IP detection failed, suggesting defaults: %s", e)
            suggested_ips = "127.0.0.1"

        schema = vol.Schema(
            {
                vol.Required(
                    "banned_ips",
                    description={"suggested_value": suggested_ips},
                ): str,
            }
        )

        return self.async_show_form(step_id="user", data_schema=schema)

custom_components/unban_local/const.py

DOMAIN = "unban_local"

custom_components/unban_local/manifest.json

{
  "domain": "unban_local",
  "name": "Local IP Unbanner",
  "documentation": "https://github.com/xxxxx/ha-unban-local",
  "codeowners": ["@xxxxx"],
  "version": "0.0.1",
  "iot_class": "local_polling",
  "config_flow": true
}

custom_components/unban_local/services.yaml

# This file is intentionally blank.

Automation

alias: Reactive Local IP Unbanner
description: Triggers when ip_bans.yaml is modified to clear internal IP bans.
triggers:
  - trigger: state
    entity_id:
      - event.folder_watcher_config_ip_bans
conditions: []
actions:
  - action: notify.mobile_app_phone
    metadata: {}
    data:
      message: ip_bans.yaml modified
      title: Home Assistant
  - action: unban_local.clear_bans
    data: {}
mode: single
1 Like

The scripts now detect and handle both IPv4 and IPv6 addresses. The updates have been made to both the shell script and the AppleScript.

Shell Script: ssh-unblock-me.sh

AppleScript: HA Unban Tool.applescript