> Advanced mode: simple mode hides the Blocked paths panel (unless the service already blocks paths) and the IP bans settings tab. Everything here keeps working either way, and a…
> Source: https://zedensix.com/homerun/docs/blocked-paths-and-ip-bans · Site index: https://zedensix.com/llms.txt

# Blocked paths and IP bans

Advanced mode: [simple mode](https://zedensix.com/homerun/docs/ui-modes) hides the Blocked paths panel (unless
the service already blocks paths) and the IP bans settings tab. Everything here
keeps working either way, and a hidden page still opens from a link.

Bots scan every public address for the same things: `.env` files, `.git`
folders, WordPress login pages, database dumps. A service can tell Traefik to
turn those requests away before they reach the app, and Homerun can ban an
address that keeps trying.

## Blocked paths

On a service's **Security** tab, **Blocked paths** takes one pattern per line. A
request whose path matches one of them gets a 403 and never reaches the app.

- A pattern matches whole path segments anywhere in the path: `.git` blocks
  `/.git`, `/.git/config` and `/app/.git/HEAD`, but not `/.github`.
- Starting a pattern with `/` matches from the root only: `/admin` blocks
  `/admin` and `/admin/users`, not `/blog/admin`.
- `*` matches anything, slashes included (`*.sql` blocks `/backups/db.sql`), and
  `?` matches one character.
- Matching ignores case.

A pattern that would match every path (`*` or `/*`) is refused: stop the service
or turn on its login wall instead.

**Presets** add a ready-made list to the box, which you can then edit:

- **WordPress probes**: `wp-admin`, `wp-login.php`, `wp-config.php*`,
  `wp-content`, `wp-includes`, `wp-json`, `xmlrpc.php`. Don't use it on a real
  WordPress site.
- **Sensitive files**: `.env` and `.env.*`, `.git`, `.git-credentials`,
  `.gitconfig`, `.svn`, `.hg`, `.aws`, `.ssh`, `.htpasswd`, `.htaccess`,
  `.npmrc`, `.DS_Store`, SQL dumps, backups and editor swap files, private keys.
- **Admin tools**: `phpmyadmin`, `phpinfo.php`, `adminer.php`, `server-status`,
  `cgi-bin`.

Saving redeploys a running service, since the rule is part of its Traefik
routing; a stopped service picks it up on its next deploy. Blocked paths apply
on every one of the service's domains, before its login wall, and its pull
request previews and canary inherit them.

Visitors see the **Blocked path** page, branded and worded under
[Settings → Error pages](https://zedensix.com/homerun/docs/error-pages). Without Traefik's dynamic config
directory (Settings → Networking), Traefik answers a bare 403 instead, and
blocked requests aren't counted towards a ban.

## IP bans

Every blocked request is counted against the address it came from. An address
that makes too many of them is banned on every service at once: Traefik answers
all its requests with a 403 until the ban ends. **Settings → IP bans** sets the
rule, on by default:

- **Blocked requests**: how many it takes (10 by default),
- **Within**: in how many minutes (10 by default, up to a day),
- **Ban for**: how many hours the ban lasts (0, for good, by default).

**Monitoring → Blocked IPs** (admins) opens on a summary of the last week,
including **Most banned on**, the service the most banned addresses were caught
on, and has two views. **Addresses** lists the banned addresses, newest first, a
page at a time and searchable by address, host or reason: why and until when,
who is behind each one and the user agent it sent, each with an **Unban**
button, and under **Being counted** every address that requested a blocked path
within the window but isn't banned yet: how many requests it made against the
threshold, the last host and path it asked for, and when. Expired bans are
lifted within a minute. Turning bans off keeps blocking the paths and only stops
new bans; bans already in place stay until they expire or you lift them.

Right after a ban, Homerun looks up who is behind the address: its reverse DNS
name, the network (AS) announcing it and its country through Team Cymru's DNS
service, and the network's owner and abuse contact over RDAP (`rdap.org`). The
result shows on Blocked IPs and in the ban's notification; a lookup that fails
leaves those fields blank. Bans placed before this existed are looked up a few a
minute. **By service** ranks the services by how many banned addresses were
caught on them; an address that hit several services counts on each.

When the lookup found an abuse contact, **Report abuse** on the ban emails it
the address, when it was banned, the host and what it asked for, over the
instance's [SMTP](https://zedensix.com/homerun/docs/configuration), and the ban then shows when it was
reported; an address is only ever reported once. **Email the abuse contact
automatically** under Settings → IP bans, off by default, sends that report on
its own as soon as a new ban's lookup finds a contact.

The dashboard's own address is never blocked by a ban, so a banned admin can
still sign in and lift it.

The rule and the [CrowdSec](#crowdsec) push can also be set from Terraform with
`homerun_ip_ban_settings`, see
[Infrastructure as code](https://zedensix.com/homerun/docs/infrastructure-as-code#resources).

### Blocked request stats

**Monitoring → Blocked IPs** opens on a **Summary** of the last 7 days across
every service, and each service's **Observability → Blocked IPs** has the same
summary for that service alone, above the addresses that hit it (marked
**Banned** when they are): how many addresses were blocked and how many requests
they made, the blocked-path pattern hit most and its share, how much
[Mean and Disrespect mode](#mean-mode-and-disrespect-mode) junk went back (fake
files and insults, in bytes), and the share of blocked requests that got junk
instead of a 403. Every request a blocked path turns away counts, bans on or
off, except from an address that's already banned (Traefik refuses those before
they reach a blocked path). Requests are kept for 7 days.

### Mean mode and Disrespect mode

Two more toggles on **Settings → IP bans**, both off by default, change what a
blocked request gets back while it still counts towards a ban:

- **Mean mode**: a request for a secret-shaped path (`.env` and `.env.*`,
  `.git/config`, `wp-config.php` and other PHP configs, `.aws/credentials`, an
  SSH private key, a `.sql` dump, an archive or `.bak`) gets a `200` and a fake
  file instead of the blocked page. The secrets in it look real (an `AKIA…` AWS
  key, an `sk_live_…` Stripe key) but are random, and an archive is half a
  megabyte of junk. A scanner that trusts it wastes its time on dead
  credentials.
- **Disrespect mode**: the same fake files, with every secret an insult
  (`PROD_API_KEY=fuckyou`) and an archive's bytes spelling one out, and any
  other blocked path gets a one-line insult instead of the blocked page.

Both only answer paths you blocked on a service: add `.env`, `.git` or `*.sql`
to its blocked paths for scanners to get there.

To hear about bans as they happen, turn on **IP banned** for a channel under
**Profile → Notifications** (it's off by default): each new ban sends the
address, until when, the host it was hitting and the reason, linking to Blocked
IPs. See [Notifications](https://zedensix.com/homerun/docs/notifications).

**Which address gets banned.** It's the address Traefik sees the request come
from. Behind Homerun's own Pangolin tunnel (Newt credentials set on the DNS
page), that's the visitor: Homerun tells Traefik to believe the visitor address
Pangolin forwards, from the tunnel container and nothing else. Behind any other
proxy or tunnel (Cloudflare's proxy, a load balancer, a Newt you run yourself),
it's the proxy. Homerun never bans a private, loopback, link-local or
carrier-grade NAT address (which is how a tunnel or a Docker network reaches
Traefik), nor an address in Cloudflare's published proxy ranges, so a proxy
can't get every visitor behind it banned. Behind such a proxy, blocked paths
still work; bans just don't happen. Only requests that really went through a
blocked-paths router count: requesting the Blocked path page directly never
does.

## CrowdSec

If a [CrowdSec](https://www.crowdsec.net) agent guards the server in front of
Homerun (a Pangolin server, typically, with its firewall bouncer), Homerun can
hand it every ban, so the address is dropped at that server before it reaches
yours, on every port.

1. On the CrowdSec host, register Homerun as a machine:
   `cscli machines add homerun --password <password>`. A bouncer key won't do,
   bouncers can only read decisions.
2. Make the Local API reachable from Homerun over HTTPS. By default it only
   listens on `127.0.0.1:8080` on its own host.
3. Under **Settings → IP bans → CrowdSec**, enter the LAPI URL, the machine id
   and its password, and save. Saving logs in first and refuses credentials that
   don't work. Clear the URL to stop.

Each new ban becomes a CrowdSec `ban` decision for the ban's length (ten years
for a ban for good) and shows up in `cscli decisions list`, with "homerun:" and
the reason as its scenario. **Unban** on Blocked IPs deletes every decision on
that address, CrowdSec's own included. CrowdSec expires decisions itself. A
failed push shows up among Homerun's own errors on
[System Logs](https://zedensix.com/homerun/docs/system-logs), and the ban still applies in Homerun's own
Traefik.

**Monitoring → CrowdSec** (admins) reads the Local API live, in three tabs, each
paged:

- **Decisions**: every decision CrowdSec's bouncers enforce right now from its
  own scenarios, manual bans and Homerun's, with the address's country and
  network when CrowdSec knows them, its reason and origin and when it ends. Bans
  Homerun pushed are marked **Homerun**. **Delete** lifts one decision; it
  doesn't lift Homerun's own ban on the same address, which stays under Blocked
  IPs. **New decision** bans an address through CrowdSec only, for a number of
  hours (0 for ten years) with a reason. Homerun's own Traefik isn't told.
- **Alerts**: what CrowdSec's scenarios caught in the last 24 hours.
- **Community blocklist**: the addresses the CrowdSec community reported, tens
  of thousands of them, searchable by address or scenario. Homerun reads the
  list at most once a minute.

A firewall bouncer drops everything from a banned address, the dashboard
included when it's served through the same server. Homerun's own exception for
the dashboard doesn't reach that far: lift the ban from another network, or with
`cscli decisions delete --ip <address>` on the CrowdSec host.
