instructions

This commit is contained in:
2026-02-28 20:52:29 +01:00
commit 460d877339
530 changed files with 62160 additions and 0 deletions

698
Docs/Architekture.md Normal file
View File

@@ -0,0 +1,698 @@
# BanGUI — Architecture
This document describes the system architecture of BanGUI, a web application for monitoring, managing, and configuring fail2ban. It defines every major component, module, and data flow so that any developer can understand how the pieces fit together before writing code.
---
## 1. High-Level Overview
BanGUI is a two-tier web application with a clear separation between frontend and backend, connected through a RESTful JSON API.
```
┌──────────────────────────────────────────────────────────────────┐
│ Browser │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ Frontend (React + Fluent UI) │ │
│ │ TypeScript · Vite · Single-Page Application │ │
│ └──────────────────────────┬─────────────────────────────────┘ │
└─────────────────────────────┼────────────────────────────────────┘
│ HTTP / JSON (REST API)
┌─────────────────────────────┼────────────────────────────────────┐
│ Server │
│ ┌──────────────────────────┴─────────────────────────────────┐ │
│ │ Backend (FastAPI) │ │
│ │ Python 3.12+ · Async · Pydantic v2 · structlog │ │
│ └─────┬──────────────┬──────────────┬────────────────────────┘ │
│ │ │ │ │
│ ┌─────┴─────┐ ┌─────┴─────┐ ┌────┴─────┐ │
│ │ SQLite │ │ fail2ban │ │ External │ │
│ │ (App DB) │ │ (Socket) │ │ APIs │ │
│ └───────────┘ └───────────┘ └──────────┘ │
└──────────────────────────────────────────────────────────────────┘
```
### Component Summary
| Component | Technology | Purpose |
|---|---|---|
| **Frontend** | TypeScript, React, Fluent UI v9, Vite | User interface — displays data, captures user input, communicates with the backend API |
| **Backend** | Python 3.12+, FastAPI, Pydantic v2, aiosqlite | Business logic, data persistence, fail2ban communication, scheduling |
| **Application Database** | SQLite (via aiosqlite) | Stores BanGUI's own data: configuration, session state, blocklist sources, import logs |
| **fail2ban** | Unix domain socket | The monitored service — BanGUI reads status, issues commands, and reads the fail2ban database |
| **External APIs** | HTTP (via aiohttp) | IP geolocation, ASN/RIR lookups, blocklist downloads |
---
## 2. Backend Architecture
The backend follows a **layered architecture** with strict separation of concerns. Dependencies flow inward: routers depend on services, services depend on repositories — never the reverse.
```
┌─────────────────────────────────┐
│ FastAPI Application │
│ (main.py) │
└──────────┬──────────────────────-┘
┌────────────────┼────────────────┐
│ │ │
┌─────┴──────┐ ┌─────┴──────┐ ┌──────┴──────┐
│ Routers │ │ Tasks │ │ Config │
│ (HTTP) │ │ (Scheduled)│ │ (Settings) │
└─────┬──────┘ └─────┬──────┘ └─────────────┘
│ │
┌─────┴───────────────┴──────┐
│ Services │
│ (Business Logic) │
└─────┬──────────────┬───────┘
│ │
┌─────┴──────┐ ┌─────┴──────┐
│Repositories│ │ External │
│ (Database) │ │ Clients │
└─────┬──────┘ └─────┬──────┘
│ │
┌─────┴──────┐ ┌─────┴──────┐
│ SQLite │ │fail2ban / │
│ │ │HTTP APIs │
└────────────┘ └────────────┘
```
### 2.1 Project Structure
```
backend/
├── app/
│ ├── __init__.py
│ ├── main.py # FastAPI app factory, lifespan, exception handlers
│ ├── config.py # Pydantic settings (env vars, .env loading)
│ ├── dependencies.py # FastAPI Depends() providers (DB, services, auth)
│ ├── models/ # Pydantic schemas
│ │ ├── auth.py # Login request/response, session models
│ │ ├── ban.py # Ban request/response/domain models
│ │ ├── jail.py # Jail request/response/domain models
│ │ ├── config.py # Configuration view/edit models
│ │ ├── blocklist.py # Blocklist source/import models
│ │ ├── history.py # Ban history models
│ │ ├── server.py # Server status, health check models
│ │ └── setup.py # Setup wizard models
│ ├── routers/ # FastAPI routers (HTTP layer only)
│ │ ├── auth.py # POST /api/auth/login, POST /api/auth/logout
│ │ ├── setup.py # POST /api/setup (first-run configuration)
│ │ ├── dashboard.py # GET /api/dashboard/status, GET /api/dashboard/bans
│ │ ├── jails.py # CRUD + controls for jails
│ │ ├── bans.py # Ban/unban actions, currently banned list
│ │ ├── config.py # View/edit fail2ban configuration
│ │ ├── history.py # Historical ban queries
│ │ ├── blocklist.py # Blocklist source management, manual import trigger
│ │ ├── geo.py # IP geolocation and lookup
│ │ └── server.py # Server settings (log level, DB purge, etc.)
│ ├── services/ # Business logic (one service per domain)
│ │ ├── auth_service.py # Password verification, session creation/validation
│ │ ├── setup_service.py # First-run setup logic, configuration persistence
│ │ ├── jail_service.py # Jail listing, start/stop/reload, status aggregation
│ │ ├── ban_service.py # Ban/unban execution, currently-banned queries
│ │ ├── config_service.py # Read/write fail2ban config, regex validation
│ │ ├── history_service.py # Historical ban queries, per-IP timeline
│ │ ├── blocklist_service.py # Download, validate, apply blocklists
│ │ ├── geo_service.py # IP-to-country resolution, ASN/RIR lookup
│ │ ├── server_service.py # Server settings, log management, DB purge
│ │ └── health_service.py # fail2ban connectivity checks, version detection
│ ├── repositories/ # Data access layer (raw queries only)
│ │ ├── settings_repo.py # App configuration CRUD in SQLite
│ │ ├── session_repo.py # Session storage and lookup
│ │ ├── blocklist_repo.py # Blocklist sources and import log persistence
│ │ └── import_log_repo.py # Import run history records
│ ├── tasks/ # APScheduler background jobs
│ │ ├── blocklist_import.py# Scheduled blocklist download and application
│ │ └── health_check.py # Periodic fail2ban connectivity probe
│ └── utils/ # Helpers, constants, shared types
│ ├── fail2ban_client.py # Async wrapper around the fail2ban socket protocol
│ ├── ip_utils.py # IP/CIDR validation and normalisation
│ ├── time_utils.py # Timezone-aware datetime helpers
│ └── constants.py # Shared constants (default paths, limits, etc.)
├── tests/
│ ├── conftest.py # Shared fixtures (test app, client, mock DB)
│ ├── test_routers/ # One test file per router
│ ├── test_services/ # One test file per service
│ └── test_repositories/ # One test file per repository
├── pyproject.toml
└── .env.example
```
### 2.2 Module Purposes
#### Routers (`app/routers/`)
The HTTP interface layer. Each router maps URL paths to handler functions. Routers parse and validate incoming requests using Pydantic models, delegate all logic to services, and return typed responses. They contain **zero business logic**.
| Router | Prefix | Purpose |
|---|---|---|
| `auth.py` | `/api/auth` | Login (password check), logout, session validation |
| `setup.py` | `/api/setup` | First-run wizard — save initial configuration |
| `dashboard.py` | `/api/dashboard` | Server status bar data, recent bans for the dashboard |
| `jails.py` | `/api/jails` | List jails, jail detail, start/stop/reload/idle controls |
| `bans.py` | `/api/bans` | Ban an IP, unban an IP, unban all, list currently banned IPs |
| `config.py` | `/api/config` | Read and write fail2ban jail/filter/server configuration |
| `history.py` | `/api/history` | Query historical bans, per-IP timeline |
| `blocklist.py` | `/api/blocklists` | CRUD blocklist sources, trigger import, view import logs |
| `geo.py` | `/api/geo` | IP geolocation lookup, ASN and RIR data |
| `server.py` | `/api/server` | Log level, log target, DB path, purge age, flush logs |
#### Services (`app/services/`)
The business logic layer. Services orchestrate operations, enforce rules, and coordinate between repositories, the fail2ban client, and external APIs. Each service covers a single domain.
| Service | Purpose |
|---|---|
| `auth_service.py` | Hashes and verifies the master password, creates and validates session tokens, enforces session expiry |
| `setup_service.py` | Validates setup input, persists initial configuration, ensures setup runs only once |
| `jail_service.py` | Retrieves jail list and details from fail2ban, aggregates metrics (banned count, failure count), sends start/stop/reload/idle commands |
| `ban_service.py` | Executes ban and unban commands via the fail2ban socket, queries the currently banned IP list, validates IPs before banning |
| `config_service.py` | Reads active jail and filter configuration from fail2ban, writes configuration changes, validates regex patterns, triggers reload |
| `history_service.py` | Queries the fail2ban database for historical ban records, builds per-IP timelines, computes ban counts and repeat-offender flags |
| `blocklist_service.py` | Downloads blocklists via aiohttp, validates IPs/CIDRs, applies bans through fail2ban or iptables, logs import results |
| `geo_service.py` | Resolves IP addresses to country, ASN, and RIR using external APIs or a local database, caches results |
| `server_service.py` | Reads and writes fail2ban server-level settings (log level, log target, syslog socket, DB location, purge age) |
| `health_service.py` | Probes fail2ban socket connectivity, retrieves server version and global stats, reports online/offline status |
#### Repositories (`app/repositories/`)
The data access layer. Repositories execute raw SQL queries against the application SQLite database. They return plain data or domain models — they never raise HTTP exceptions or contain business logic.
| Repository | Purpose |
|---|---|
| `settings_repo.py` | CRUD operations for application settings (master password hash, DB path, fail2ban socket path, preferences) |
| `session_repo.py` | Store, retrieve, and delete session records for authentication |
| `blocklist_repo.py` | Persist blocklist source definitions (name, URL, enabled/disabled) |
| `import_log_repo.py` | Record import run results (timestamp, source, IPs imported, errors) for the import log view |
#### Models (`app/models/`)
Pydantic schemas that define data shapes and validation. Models are split into three categories per domain:
- **Request models** — validate incoming API data (e.g., `BanRequest`, `LoginRequest`)
- **Response models** — shape outgoing API data (e.g., `JailResponse`, `BanListResponse`)
- **Domain models** — internal representations used between services and repositories (e.g., `Ban`, `Jail`)
#### Tasks (`app/tasks/`)
APScheduler background jobs that run on a schedule without user interaction.
| Task | Purpose |
|---|---|
| `blocklist_import.py` | Downloads all enabled blocklist sources, validates entries, applies bans, records results in the import log |
| `health_check.py` | Periodically pings the fail2ban socket and updates the cached server status so the frontend always has fresh data |
#### Utils (`app/utils/`)
Pure helper modules with no framework dependencies.
| Module | Purpose |
|---|---|
| `fail2ban_client.py` | Async client that communicates with fail2ban via its Unix domain socket — sends commands and parses responses using the fail2ban protocol. Modelled after [`./fail2ban-master/fail2ban/client/csocket.py`](../fail2ban-master/fail2ban/client/csocket.py) and [`./fail2ban-master/fail2ban/client/fail2banclient.py`](../fail2ban-master/fail2ban/client/fail2banclient.py). |
| `ip_utils.py` | Validates IPv4/IPv6 addresses and CIDR ranges using the `ipaddress` stdlib module, normalises formats |
| `time_utils.py` | Timezone-aware datetime construction, formatting helpers, time-range calculations |
| `constants.py` | Shared constants: default socket path, default database path, time-range presets, limits |
#### Configuration (`app/config.py`)
A single Pydantic settings model that loads all configuration from environment variables (prefixed `BANGUI_`) and an optional `.env` file. Validated at startup — the application refuses to start if required values are missing.
#### Dependencies (`app/dependencies.py`)
FastAPI `Depends()` providers that inject shared resources into route handlers: the database connection, service instances, the authenticated session, and the fail2ban client. This is the wiring layer that connects routers to services without tight coupling.
#### Application Entry Point (`app/main.py`)
The FastAPI app factory. Responsibilities:
- Creates the `FastAPI` instance with metadata (title, version, docs URL)
- Registers the **lifespan** context manager (startup: open DB, create aiohttp session, start scheduler; shutdown: close all)
- Mounts all routers
- Registers global exception handlers that map domain exceptions to HTTP status codes
- Applies the setup-redirect middleware (redirects all requests to `/api/setup` when no configuration exists)
---
## 3. Frontend Architecture
The frontend is a React single-page application built with TypeScript, Vite, and Fluent UI v9. It communicates exclusively with the backend REST API — it never accesses fail2ban, the database, or external services directly.
```
┌──────────────────────────────────────────────────────────────┐
│ React Application │
│ │
│ ┌──────────┐ ┌────────────┐ ┌──────────────────┐ │
│ │ Pages │───▶│ Components │───▶│ Fluent UI v9 │ │
│ └────┬─────┘ └────────────┘ └──────────────────┘ │
│ │ │
│ ┌────┴─────┐ ┌────────────┐ ┌──────────────────┐ │
│ │ Hooks │───▶│ API Layer │───▶│ Backend (REST) │ │
│ └──────────┘ └────────────┘ └──────────────────┘ │
│ │
│ ┌──────────┐ ┌────────────┐ ┌──────────────────┐ │
│ │Providers │ │ Types │ │ Theme │ │
│ │(Context) │ │(Interfaces)│ │(Tokens, Styles) │ │
│ └──────────┘ └────────────┘ └──────────────────┘ │
└──────────────────────────────────────────────────────────────┘
```
### 3.1 Project Structure
```
frontend/
├── public/
├── src/
│ ├── api/ # API client and per-domain request functions
│ │ ├── client.ts # Central fetch wrapper (typed GET/POST/PUT/DELETE)
│ │ ├── endpoints.ts # API path constants
│ │ ├── auth.ts # Login, logout, session check
│ │ ├── dashboard.ts # Dashboard status and ban list
│ │ ├── jails.ts # Jail CRUD and controls
│ │ ├── bans.ts # Ban/unban actions, banned list
│ │ ├── config.ts # Configuration read/write
│ │ ├── history.ts # Ban history queries
│ │ ├── blocklist.ts # Blocklist source management
│ │ ├── geo.ts # IP lookup / geolocation
│ │ └── server.ts # Server settings
│ ├── assets/ # Static images, fonts, icons
│ ├── components/ # Reusable UI components
│ │ ├── BanTable.tsx # Data table for ban entries
│ │ ├── JailCard.tsx # Summary card for a jail
│ │ ├── StatusBar.tsx # Server status indicator strip
│ │ ├── TimeRangeSelector.tsx # Quick preset picker (24h, 7d, 30d, 365d)
│ │ ├── IpInput.tsx # IP address input with validation
│ │ ├── RegexTester.tsx # Side-by-side regex match preview
│ │ ├── WorldMap.tsx # Country-outline map with ban counts
│ │ ├── ImportLogTable.tsx # Blocklist import run history
│ │ ├── ConfirmDialog.tsx # Reusable confirmation modal
│ │ └── ... # (additional shared components)
│ ├── hooks/ # Custom React hooks (stateful logic + API calls)
│ │ ├── useAuth.ts # Login state, login/logout actions
│ │ ├── useBans.ts # Fetch ban list for a time range
│ │ ├── useJails.ts # Fetch jail list and details
│ │ ├── useConfig.ts # Fetch and update configuration
│ │ ├── useHistory.ts # Fetch historical ban data
│ │ ├── useBlocklists.ts # Fetch and manage blocklist sources
│ │ ├── useServerStatus.ts # Poll server health / status
│ │ └── useGeo.ts # IP lookup hook
│ ├── layouts/ # Page-level layout wrappers
│ │ └── AppLayout.tsx # Sidebar navigation + header + content area
│ ├── pages/ # Route-level page components (one per route)
│ │ ├── SetupPage.tsx # First-run wizard
│ │ ├── LoginPage.tsx # Password prompt
│ │ ├── DashboardPage.tsx # Ban overview, status bar, access list
│ │ ├── WorldMapPage.tsx # Geographical ban map + access table
│ │ ├── JailsPage.tsx # Jail list, detail, controls, ban/unban
│ │ ├── ConfigPage.tsx # Configuration viewer/editor
│ │ ├── HistoryPage.tsx # Ban history browser
│ │ └── BlocklistPage.tsx # Blocklist source management + import log
│ ├── providers/ # React context providers
│ │ ├── AuthProvider.tsx # Authentication state and guards
│ │ └── ThemeProvider.tsx # Light/dark theme switching
│ ├── theme/ # Fluent UI theme definitions
│ │ ├── customTheme.ts # Brand colour ramp, light and dark themes
│ │ └── tokens.ts # Spacing, sizing, and z-index constants
│ ├── types/ # Shared TypeScript interfaces
│ │ ├── auth.ts # LoginRequest, SessionInfo
│ │ ├── ban.ts # Ban, BanListResponse, BanRequest
│ │ ├── jail.ts # Jail, JailDetail, JailListResponse
│ │ ├── config.ts # ConfigSection, ConfigUpdateRequest
│ │ ├── history.ts # HistoryEntry, IpTimeline
│ │ ├── blocklist.ts # BlocklistSource, ImportLogEntry
│ │ ├── geo.ts # GeoInfo, AsnInfo
│ │ ├── server.ts # ServerStatus, ServerSettings
│ │ └── api.ts # ApiError, PaginatedResponse
│ ├── utils/ # Pure helper functions
│ │ ├── formatDate.ts # Date/time formatting with timezone support
│ │ ├── formatIp.ts # IP display formatting
│ │ └── constants.ts # Frontend constants (time presets, etc.)
│ ├── App.tsx # Root: FluentProvider + BrowserRouter + routes
│ ├── main.tsx # Vite entry point
│ └── vite-env.d.ts # Vite type shims
├── tsconfig.json
├── vite.config.ts
└── package.json
```
### 3.2 Module Purposes
#### Pages (`src/pages/`)
Top-level route components. Each page composes layout, components, and hooks to create a full screen. Pages contain **no business logic** — they orchestrate what is displayed and delegate data fetching to hooks.
| Page | Route | Purpose |
|---|---|---|
| `SetupPage` | `/setup` | First-run wizard: set master password, database path, fail2ban connection, preferences |
| `LoginPage` | `/login` | Single-field password prompt; redirects to requested page after success |
| `DashboardPage` | `/` | Server status bar, ban list table, access list tab, time-range selector |
| `WorldMapPage` | `/map` | World map with per-country ban counts, companion access table, country filter |
| `JailsPage` | `/jails` | Jail overview list, jail detail panel, controls (start/stop/reload), ban/unban forms, IP lookup, whitelist management |
| `ConfigPage` | `/config` | View and edit jail parameters, filter regex, server settings, regex tester, add log observation |
| `HistoryPage` | `/history` | Browse all past bans, filter by jail/IP/time, per-IP timeline drill-down |
| `BlocklistPage` | `/blocklists` | Manage blocklist sources, schedule configuration, import log, manual import trigger |
#### Components (`src/components/`)
Reusable UI building blocks. Components receive data via props, emit changes via callbacks, and never call the API directly. Built exclusively with Fluent UI v9 components.
| Component | Purpose |
|---|---|
| `StatusBar` | Displays fail2ban server status (online/offline, version, jail count, total bans) |
| `BanTable` | Sortable data table for ban entries with columns for time, IP, jail, country, etc. |
| `JailCard` | Summary card showing jail name, status badge, key metrics |
| `TimeRangeSelector` | Quick-preset picker for filtering data (24h, 7d, 30d, 365d) |
| `IpInput` | IP address text field with inline validation |
| `WorldMap` | SVG/Canvas country-outline map with count overlays and click-to-filter |
| `RegexTester` | Side-by-side sample log + regex input with live match highlighting |
| `ImportLogTable` | Table displaying blocklist import history |
| `ConfirmDialog` | Reusable Fluent UI Dialog for destructive action confirmations |
#### Hooks (`src/hooks/`)
Encapsulate all stateful logic, side effects, and API calls. Components and pages consume hooks to stay declarative.
| Hook | Purpose |
|---|---|
| `useAuth` | Manages login state, provides `login()`, `logout()`, and `isAuthenticated` |
| `useBans` | Fetches ban list for a given time range, returns `{ bans, loading, error }` |
| `useJails` | Fetches jail list and individual jail detail |
| `useConfig` | Reads and writes fail2ban configuration |
| `useHistory` | Queries historical ban data with filters |
| `useBlocklists` | Manages blocklist sources and import triggers |
| `useServerStatus` | Polls the server status endpoint at an interval |
| `useGeo` | Performs IP geolocation lookups on demand |
#### API Layer (`src/api/`)
A thin typed wrapper around `fetch`. All HTTP communication is centralised here — components and hooks never construct HTTP requests directly.
| Module | Purpose |
|---|---|
| `client.ts` | Central `get<T>`, `post<T>`, `put<T>`, `del<T>` functions with error handling and credentials |
| `endpoints.ts` | All API path constants in one place — no hard-coded URLs anywhere else |
| `auth.ts` | `login()`, `logout()`, `checkSession()` |
| `dashboard.ts` | `fetchStatus()`, `fetchRecentBans()` |
| `jails.ts` | `fetchJails()`, `fetchJailDetail()`, `startJail()`, `stopJail()`, `reloadJail()` |
| `bans.ts` | `banIp()`, `unbanIp()`, `unbanAll()`, `fetchBannedIps()` |
| `config.ts` | `fetchConfig()`, `updateConfig()`, `testRegex()` |
| `history.ts` | `fetchHistory()`, `fetchIpTimeline()` |
| `blocklist.ts` | `fetchSources()`, `addSource()`, `removeSource()`, `triggerImport()`, `fetchImportLog()` |
| `geo.ts` | `lookupIp()` |
| `server.ts` | `fetchServerSettings()`, `updateServerSettings()` |
#### Types (`src/types/`)
Shared TypeScript interfaces and type aliases. Purely declarative — no runtime code. Grouped by domain. Any type used by two or more files lives here.
#### Providers (`src/providers/`)
React context providers for application-wide concerns.
| Provider | Purpose |
|---|---|
| `AuthProvider` | Holds authentication state, wraps protected routes, redirects unauthenticated users to `/login` |
| `ThemeProvider` | Manages light/dark theme selection, supplies the active Fluent UI theme to `FluentProvider` |
#### Theme (`src/theme/`)
Fluent UI custom theme definitions and design token constants. No component logic — only colours, spacing, and sizing values.
#### Utils (`src/utils/`)
Pure helper functions with no React or framework dependency. Date formatting, IP display formatting, shared constants.
---
## 4. Data Flow
### 4.1 Request Lifecycle
Every user action follows this flow through the system:
```
User Action (click, form submit)
Page / Component
│ calls hook
Hook (useXxx)
│ calls API function
API Layer (src/api/)
│ HTTP request
FastAPI Router (app/routers/)
│ validates input (Pydantic)
│ calls Depends() for auth + services
Service (app/services/)
│ enforces business rules
│ calls repository or fail2ban client
Repository (app/repositories/) or fail2ban Client (app/utils/)
│ executes SQL query │ sends socket command
▼ ▼
SQLite Database fail2ban Server
│ │
└──────────── response bubbles back up ─────┘
```
### 4.2 Authentication Flow
```
┌─────────┐ POST /api/auth/login ┌─────────────┐
│ Login │ ─────────────────────────────▶│ auth router │
│ Page │ { password: "***" } │ │
└─────────┘ └──────┬───────┘
┌──────┴───────┐
│ auth_service │
│ - verify hash │
│ - create token│
└──────┬───────┘
┌──────┴───────┐
│ session_repo │
│ - store token │
└──────┬───────┘
Set-Cookie: session=<token> │
◀─────────────────────────────────────────────────┘
```
- The master password is hashed and stored during setup.
- On login, the submitted password is verified against the stored hash.
- A session token is created, stored in the database, and returned as an HTTP-only cookie.
- Every subsequent request is authenticated via the session cookie using a FastAPI dependency.
- The `AuthProvider` on the frontend guards all routes except `/setup` and `/login`.
### 4.3 fail2ban Communication
BanGUI communicates with fail2ban through its **Unix domain socket** using the fail2ban client-server protocol.
```
┌────────────────────┐ ┌──────────────────┐
│ ban_service.py │ │ fail2ban server │
│ jail_service.py │──socket──│ │
│ config_service.py │ │ /var/run/fail2ban│
│ health_service.py │ │ /fail2ban.sock │
└────────────────────┘ └──────────────────┘
```
The `fail2ban_client.py` utility module wraps this communication:
- Opens an async connection to the Unix socket
- Serialises commands using the fail2ban protocol (pickle-based, see [`./fail2ban-master/fail2ban/client/csocket.py`](../fail2ban-master/fail2ban/client/csocket.py))
- Parses responses into typed Python objects
- Handles connection errors gracefully (timeout, socket not found, permission denied)
> **Reference source:** The vendored fail2ban source at [`./fail2ban-master`](../fail2ban-master) is included in the repository as an authoritative protocol reference. When implementing or debugging socket communication, consult:
>
> | File | What it documents |
> |---|---|
> | [`./fail2ban-master/fail2ban/client/csocket.py`](../fail2ban-master/fail2ban/client/csocket.py) | `CSocket` class — low-level Unix socket connection, pickle serialisation, `CSPROTO.END` framing |
> | [`./fail2ban-master/fail2ban/client/fail2banclient.py`](../fail2ban-master/fail2ban/client/fail2banclient.py) | `Fail2banClient` — command dispatch, argument handling, response beautification |
> | [`./fail2ban-master/fail2ban/client/beautifier.py`](../fail2ban-master/fail2ban/client/beautifier.py) | Response parser — converts raw server replies into human-readable / structured output |
> | [`./fail2ban-master/fail2ban/protocol.py`](../fail2ban-master/fail2ban/protocol.py) | `CSPROTO` constants and the full list of supported commands with descriptions |
> | [`./fail2ban-master/fail2ban/client/configreader.py`](../fail2ban-master/fail2ban/client/configreader.py) | Config file parsing used by fail2ban — reference for understanding jail/filter structure |
**Key commands used:**
| Command | Purpose |
|---|---|
| `status` | Get global server status (number of jails, fail2ban version) |
| `status <jail>` | Get jail detail (banned IPs, failure count, filter info) |
| `set <jail> banip <ip>` | Ban an IP in a specific jail |
| `set <jail> unbanip <ip>` | Unban an IP from a specific jail |
| `set <jail> idle on/off` | Toggle jail idle mode |
| `start/stop <jail>` | Start or stop a jail |
| `reload <jail>` | Reload a single jail configuration |
| `reload` | Reload all jails |
| `get <jail> ...` | Read jail settings (findtime, bantime, maxretry, filter, actions, etc.) |
| `set <jail> ...` | Write jail settings |
| `set loglevel <level>` | Change server log level |
| `set logtarget <target>` | Change server log target |
| `set dbpurgeage <seconds>` | Set database purge age |
| `flushlogs` | Flush and re-open log files |
### 4.4 fail2ban Database Access
In addition to the live socket, BanGUI reads the **fail2ban SQLite database** directly for historical data that the socket protocol does not expose (ban history, past log matches). This is read-only access.
```
history_service.py ──read-only──▶ fail2ban.db (SQLite)
```
The fail2ban database contains:
- `bans` table — historical ban records (IP, jail, timestamp, ban data)
- `jails` table — jail definitions
- `logs` table — matched log lines per ban
BanGUI queries these tables to power the Ban History page and the per-IP timeline view.
### 4.5 External API Communication
```
geo_service.py ──aiohttp──▶ IP Geolocation API (country, ASN, RIR)
blocklist_service.py ──aiohttp──▶ Blocklist URLs (plain-text IP lists)
```
All external HTTP calls go through a shared `aiohttp.ClientSession` created during startup and closed during shutdown. External data is validated before use (IP format, response structure).
---
## 5. Database Design
BanGUI maintains its **own SQLite database** (separate from the fail2ban database) to store application state.
### 5.1 Application Database Tables
| Table | Purpose |
|---|---|
| `settings` | Key-value store for application configuration (master password hash, fail2ban socket path, database path, timezone, session duration) |
| `sessions` | Active session tokens with expiry timestamps |
| `blocklist_sources` | Registered blocklist URLs (id, name, url, enabled, created_at, updated_at) |
| `import_logs` | Record of every blocklist import run (id, source_id, timestamp, ips_imported, ips_skipped, errors, status) |
### 5.2 Database Boundaries
| Database | Owner | BanGUI Access |
|---|---|---|
| BanGUI application DB (`bangui.db`) | BanGUI | Read + Write |
| fail2ban DB (`fail2ban.db`) | fail2ban | Read-only (for history queries) |
---
## 6. Authentication & Session Management
- **Single-user model** — one master password, no usernames.
- Password is hashed with a strong algorithm (e.g., bcrypt or argon2) and stored in the application database during setup.
- Sessions are token-based, stored server-side in the `sessions` table, and delivered to the browser as HTTP-only secure cookies.
- Session expiry is configurable (set during setup, stored in `settings`).
- The frontend `AuthProvider` checks session validity on mount and redirects to `/login` if invalid.
- The backend `dependencies.py` provides an `authenticated` dependency that validates the session cookie on every protected endpoint.
---
## 7. Scheduling
APScheduler 4.x (async mode) manages recurring background tasks.
```
┌──────────────────────┐
│ APScheduler │
│ (async, in-process) │
├──────────────────────┤
│ blocklist_import │ ── runs on configured schedule (default: daily 03:00)
│ health_check │ ── runs every 30 seconds
└──────────────────────┘
```
- The scheduler is started during the FastAPI lifespan startup and stopped during shutdown.
- Job schedules are persisted in the application database so they survive restarts.
- Users can modify the blocklist import schedule through the web interface.
- A manual "Run Now" button triggers the blocklist import job outside the schedule.
---
## 8. API Design
### 8.1 Conventions
- All endpoints are grouped under `/api/` prefix.
- JSON request and response bodies, validated by Pydantic models.
- Authentication via session cookie on all endpoints except `/api/setup` and `/api/auth/login`.
- Setup-redirect middleware: while no configuration exists, all endpoints return `303 See Other``/api/setup`.
- Standard HTTP status codes: `200` success, `201` created, `204` no content, `400` bad request, `401` unauthorized, `404` not found, `422` validation error, `500` server error.
- Error responses follow a consistent shape: `{ "detail": "Human-readable message" }`.
### 8.2 Endpoint Groups
| Group | Endpoints | Description |
|---|---|---|
| **Auth** | `POST /login`, `POST /logout` | Session management |
| **Setup** | `POST /setup` | First-run configuration |
| **Dashboard** | `GET /status`, `GET /bans` | Overview data for the main page |
| **Jails** | `GET /`, `GET /:name`, `POST /:name/start`, `POST /:name/stop`, `POST /:name/reload`, `POST /reload-all` | Jail listing and controls |
| **Bans** | `POST /ban`, `POST /unban`, `POST /unban-all`, `GET /banned` | Ban management |
| **Config** | `GET /`, `PUT /`, `POST /test-regex` | Configuration viewing and editing |
| **History** | `GET /`, `GET /ip/:ip` | Historical ban browsing |
| **Blocklists** | `GET /sources`, `POST /sources`, `DELETE /sources/:id`, `POST /import`, `GET /import-log` | Blocklist management |
| **Geo** | `GET /lookup/:ip` | IP geolocation and enrichment |
| **Server** | `GET /settings`, `PUT /settings`, `POST /flush-logs` | Server-level settings |
---
## 9. Deployment Architecture
```
┌──────────────────────────────────────────────────┐
│ Host Machine │
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ Reverse Proxy (nginx / caddy) │ │
│ │ - TLS termination │ │
│ │ - /api/* → backend (uvicorn) │ │
│ │ - /* → frontend (static files) │ │
│ └──────────────┬───────────────┬──────────────┘ │
│ │ │ │
│ ┌──────────────┴───┐ ┌───────┴──────────────┐ │
│ │ Backend │ │ Frontend │ │
│ │ uvicorn + FastAPI │ │ Static build (Vite) │ │
│ │ (port 8000) │ │ (served by proxy) │ │
│ └────────┬──────────┘ └──────────────────────┘ │
│ │ │
│ ┌────────┴──────────────────────────────────┐ │
│ │ fail2ban (systemd service) │ │
│ │ Socket: /var/run/fail2ban/fail2ban.sock │ │
│ │ Database: /var/lib/fail2ban/fail2ban.db │ │
│ └───────────────────────────────────────────┘ │
└──────────────────────────────────────────────────┘
```
- The backend runs as an ASGI server (uvicorn) behind a reverse proxy.
- The frontend is built to static files by Vite and served directly by the reverse proxy.
- The backend process needs read access to the fail2ban socket and the fail2ban database.
- Both the application database and the fail2ban database reside on the same host.
---
## 10. Design Principles
These principles govern all architectural decisions in BanGUI.
| Principle | Application |
|---|---|
| **Separation of Concerns** | Frontend and backend are independent. Backend layers (router → service → repository) never mix responsibilities. |
| **Single Responsibility** | Each module, service, and component has one well-defined job. |
| **Dependency Inversion** | Services depend on abstractions (protocols), not concrete implementations. FastAPI `Depends()` wires everything. |
| **Async Everything** | All I/O is non-blocking. No synchronous database, HTTP, or socket calls anywhere in the backend. |
| **Validate at the Boundary** | Pydantic models validate all data entering the backend. TypeScript types enforce structure on the frontend. |
| **Fail Fast** | Configuration is validated at startup. Invalid input is rejected immediately with clear errors. |
| **Composition over Inheritance** | Small, focused objects are composed together rather than building deep class hierarchies. |
| **DRY** | Shared logic lives in utils, hooks, or base services — never duplicated across modules. |
| **KISS** | The simplest correct solution wins. No premature abstractions or over-engineering. |
| **YAGNI** | Only build what is needed now. Extend when a real requirement appears. |

430
Docs/Backend-Development.md Normal file
View File

@@ -0,0 +1,430 @@
# Backend Development — Rules & Guidelines
Rules and conventions every backend developer must follow. Read this before writing your first line of code.
---
## 1. Language & Typing
- **Python 3.12+** is the minimum version.
- **Every** function, method, and variable must have explicit type annotations — no exceptions.
- Use `str`, `int`, `float`, `bool`, `None` for primitives.
- Use `list[T]`, `dict[K, V]`, `set[T]`, `tuple[T, ...]` (lowercase, built-in generics) — never `typing.List`, `typing.Dict`, etc.
- Use `T | None` instead of `Optional[T]`.
- Use `TypeAlias`, `TypeVar`, `Protocol`, and `NewType` when they improve clarity.
- Return types are **mandatory** — including `-> None`.
- Never use `Any` unless there is no other option and a comment explains why.
- Run `mypy --strict` (or `pyright` in strict mode) — the codebase must pass with zero errors.
```python
# Good
def get_jail_by_name(name: str) -> Jail | None:
...
# Bad — missing types
def get_jail_by_name(name):
...
```
---
## 2. Core Libraries
| Purpose | Library | Notes |
|---|---|---|
| Web framework | **FastAPI** | Async endpoints only. |
| Data validation & settings | **Pydantic v2** | All request/response bodies and config models. |
| Async HTTP client | **aiohttp** (`ClientSession`) | For external calls (blocklists, IP lookups). |
| Scheduling | **APScheduler 4.x** (async) | Blocklist imports, periodic health checks. |
| Structured logging | **structlog** | Every log call must use structlog — never `print()` or `logging` directly. |
| Database | **aiosqlite** | Async SQLite access for the application database. |
| Testing | **pytest** + **pytest-asyncio** + **httpx** (`AsyncClient`) | Every feature needs tests. |
| Mocking | **unittest.mock** / **pytest-mock** | Isolate external dependencies. |
| Date & time | **datetime** (stdlib) — always timezone-aware | Use `datetime.datetime.now(datetime.UTC)`. Never naive datetimes. |
| IP / Network | **ipaddress** (stdlib) | Validate and normalise IPs and CIDR ranges. |
| Environment / config | **pydantic-settings** | Load `.env` and environment variables into typed models. |
| fail2ban integration | **fail2ban client** (bundled) | Use the local copy at [`./fail2ban-master`](../fail2ban-master). Import from [`./fail2ban-master/fail2ban/client`](../fail2ban-master/fail2ban/client) to communicate with the fail2ban socket. Do **not** install fail2ban as a pip package. |
### fail2ban Client Usage
The repository ships with a vendored copy of fail2ban located at `./fail2ban-master`.
All communication with the fail2ban daemon must go through the client classes found in `./fail2ban-master/fail2ban/client`.
Add the project root to `sys.path` (or configure it in `pyproject.toml` as a path dependency) so that `from fail2ban.client ...` resolves to the bundled copy.
```python
import sys
from pathlib import Path
# Ensure the bundled fail2ban is importable
sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "fail2ban-master"))
from fail2ban.client.csocket import CSSocket # noqa: E402
```
### Libraries you must NOT use
- `requests` — use `aiohttp` (async).
- `flask` — we use FastAPI.
- `celery` — we use APScheduler.
- `print()` for logging — use `structlog`.
- `json.loads` / `json.dumps` on Pydantic models — use `.model_dump()` / `.model_validate()`.
---
## 3. Project Structure
```
backend/
├── app/
│ ├── __init__.py
│ ├── main.py # FastAPI app factory, lifespan
│ ├── config.py # Pydantic settings
│ ├── dependencies.py # FastAPI dependency providers
│ ├── models/ # Pydantic schemas (request, response, domain)
│ ├── routers/ # FastAPI routers grouped by feature
│ ├── services/ # Business logic — one service per domain
│ ├── repositories/ # Database access layer
│ ├── tasks/ # APScheduler jobs
│ └── utils/ # Helpers, constants, shared types
├── tests/
│ ├── conftest.py
│ ├── test_routers/
│ ├── test_services/
│ └── test_repositories/
├── pyproject.toml
└── .env.example
```
- **Routers** receive requests, validate input via Pydantic, and delegate to **services**.
- **Services** contain business logic and call **repositories** or external clients.
- **Repositories** handle raw database queries — nothing else.
- Never put business logic inside routers or repositories.
---
## 4. FastAPI Conventions
- Use **async def** for every endpoint — no sync endpoints.
- Every endpoint must declare explicit **response models** (`response_model=...`).
- Use **Pydantic models** for request bodies and query parameters — never raw dicts.
- Use **Depends()** for dependency injection (database sessions, services, auth).
- Group endpoints into routers by feature domain (`routers/jails.py`, `routers/bans.py`, …).
- Use appropriate HTTP status codes: `201` for creation, `204` for deletion with no body, `404` for not found, etc.
- Use **HTTPException** or custom exception handlers — never return error dicts manually.
```python
from fastapi import APIRouter, Depends, HTTPException, status
from app.models.jail import JailResponse, JailListResponse
from app.services.jail_service import JailService
router: APIRouter = APIRouter(prefix="/api/jails", tags=["Jails"])
@router.get("/", response_model=JailListResponse)
async def list_jails(service: JailService = Depends()) -> JailListResponse:
jails: list[JailResponse] = await service.get_all_jails()
return JailListResponse(jails=jails)
```
---
## 5. Pydantic Models
- Every model inherits from `pydantic.BaseModel`.
- Use `model_config = ConfigDict(strict=True)` where appropriate.
- Field names use **snake_case** in Python, export as **camelCase** to the frontend via alias generators if needed.
- Validate at the boundary — once data enters a Pydantic model it is trusted.
- Use `Field(...)` with descriptions for every field to keep auto-generated docs useful.
- Separate **request models**, **response models**, and **domain (internal) models** — do not reuse one model for all three.
```python
from pydantic import BaseModel, Field
from datetime import datetime
class BanResponse(BaseModel):
ip: str = Field(..., description="Banned IP address")
jail: str = Field(..., description="Jail that issued the ban")
banned_at: datetime = Field(..., description="UTC timestamp of the ban")
expires_at: datetime | None = Field(None, description="UTC expiry, None if permanent")
ban_count: int = Field(..., ge=1, description="Number of times this IP was banned")
```
---
## 6. Async Rules
- **Never** call blocking / synchronous I/O in an async function — no `time.sleep()`, no synchronous file reads, no `requests.get()`.
- Use `aiohttp.ClientSession` for HTTP calls, `aiosqlite` for database access.
- Use `asyncio.TaskGroup` (Python 3.11+) when you need to run independent coroutines concurrently.
- Long-running startup/shutdown logic goes into the **FastAPI lifespan** context manager.
- Shared resources (DB connections, HTTP sessions) are created once during startup and closed during shutdown — never inside request handlers.
```python
from contextlib import asynccontextmanager
from collections.abc import AsyncGenerator
from fastapi import FastAPI
import aiohttp
import aiosqlite
@asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncGenerator[None]:
# Startup
app.state.http_session = aiohttp.ClientSession()
app.state.db = await aiosqlite.connect("bangui.db")
yield
# Shutdown
await app.state.http_session.close()
await app.state.db.close()
```
---
## 7. Logging
- Use **structlog** for every log message.
- Bind contextual key-value pairs — never format strings manually.
- Log levels: `debug` for development detail, `info` for operational events, `warning` for recoverable issues, `error` for failures, `critical` for fatal problems.
- Never log sensitive data (passwords, tokens, session IDs).
```python
import structlog
log: structlog.stdlib.BoundLogger = structlog.get_logger()
async def ban_ip(ip: str, jail: str) -> None:
log.info("banning_ip", ip=ip, jail=jail)
try:
await _execute_ban(ip, jail)
log.info("ip_banned", ip=ip, jail=jail)
except BanError as exc:
log.error("ban_failed", ip=ip, jail=jail, error=str(exc))
raise
```
---
## 8. Error Handling
- Define **custom exception classes** for domain errors (e.g., `JailNotFoundError`, `BanFailedError`).
- Catch specific exceptions — never bare `except:` or `except Exception:` without re-raising.
- Map domain exceptions to HTTP status codes via FastAPI **exception handlers** registered on the app.
- Always log errors with context before raising.
```python
class JailNotFoundError(Exception):
def __init__(self, name: str) -> None:
self.name: str = name
super().__init__(f"Jail '{name}' not found")
# In main.py
@app.exception_handler(JailNotFoundError)
async def jail_not_found_handler(request: Request, exc: JailNotFoundError) -> JSONResponse:
return JSONResponse(status_code=404, content={"detail": f"Jail '{exc.name}' not found"})
```
---
## 9. Testing
- **Every** new feature or bug fix must include tests.
- Tests live in `tests/` mirroring the `app/` structure.
- Use `pytest` with `pytest-asyncio` for async tests.
- Use `httpx.AsyncClient` to test FastAPI endpoints (not `TestClient` which is sync).
- Mock external dependencies (fail2ban socket, aiohttp calls) — tests must never touch real infrastructure.
- Aim for **>80 % line coverage** — critical paths (auth, banning, scheduling) must be 100 %.
- Test names follow `test_<unit>_<scenario>_<expected>` pattern.
```python
import pytest
from httpx import AsyncClient, ASGITransport
from app.main import create_app
@pytest.fixture
async def client() -> AsyncClient:
app = create_app()
transport: ASGITransport = ASGITransport(app=app)
async with AsyncClient(transport=transport, base_url="http://test") as ac:
yield ac
@pytest.mark.asyncio
async def test_list_jails_returns_200(client: AsyncClient) -> None:
response = await client.get("/api/jails/")
assert response.status_code == 200
data: dict = response.json()
assert "jails" in data
```
---
## 10. Code Style & Tooling
| Tool | Purpose |
|---|---|
| **Ruff** | Linter and formatter (replaces black, isort, flake8). |
| **mypy** or **pyright** | Static type checking in strict mode. |
| **pre-commit** | Run ruff + type checker before every commit. |
- Line length: **120 characters** max.
- Strings: use **double quotes** (`"`).
- Imports: sorted by ruff — stdlib → third-party → local, one import per line.
- No unused imports, no unused variables, no `# type: ignore` without explanation.
- Docstrings in **Google style** on every public function, class, and module.
---
## 11. Configuration & Secrets
- All configuration lives in **environment variables** loaded through **pydantic-settings**.
- Secrets (master password hash, session key) are **never** committed to the repository.
- Provide a `.env.example` with all keys and placeholder values.
- Validate config at startup — fail fast with a clear error if a required value is missing.
```python
from pydantic_settings import BaseSettings
from pydantic import Field
class Settings(BaseSettings):
database_path: str = Field("bangui.db", description="Path to SQLite database")
fail2ban_socket: str = Field("/var/run/fail2ban/fail2ban.sock", description="fail2ban socket path")
session_secret: str = Field(..., description="Secret key for session signing")
log_level: str = Field("info", description="Logging level")
model_config = {"env_prefix": "BANGUI_", "env_file": ".env"}
```
---
## 12. Git & Workflow
- **Branch naming:** `feature/<short-description>`, `fix/<short-description>`, `chore/<short-description>`.
- **Commit messages:** imperative tense, max 72 chars first line (`Add jail reload endpoint`, `Fix ban history query`).
- Every merge request must pass: ruff, type checker, all tests.
- Do not merge with failing CI.
- Keep pull requests small and focused — one feature or fix per PR.
---
## 13. Coding Principles
These principles are **non-negotiable**. Every backend contributor must internalise and apply them daily.
### 13.1 Clean Code
- Write code that **reads like well-written prose** — a new developer should understand intent without asking.
- **Meaningful names** — variables, functions, and classes must reveal their purpose. Avoid abbreviations (`cnt`, `mgr`, `tmp`) unless universally understood.
- **Small functions** — each function does exactly one thing. If you need a comment to explain a block inside a function, extract it into its own function.
- **No magic numbers or strings** — use named constants.
- **Boy Scout Rule** — leave every file cleaner than you found it.
- **Avoid deep nesting** — prefer early returns (guard clauses) to keep the happy path at the top indentation level.
```python
# Good — guard clause, clear name, one job
async def get_active_ban(ip: str, jail: str) -> Ban:
ban: Ban | None = await repo.find_ban(ip=ip, jail=jail)
if ban is None:
raise BanNotFoundError(ip=ip, jail=jail)
if ban.is_expired():
raise BanExpiredError(ip=ip, jail=jail)
return ban
# Bad — nested, vague name
async def check(ip, j):
b = await repo.find_ban(ip=ip, jail=j)
if b:
if not b.is_expired():
return b
else:
raise Exception("expired")
else:
raise Exception("not found")
```
### 13.2 Separation of Concerns (SoC)
- Each module, class, and function must have a **single, well-defined responsibility**.
- **Routers** → HTTP layer only (parse requests, return responses).
- **Services** → business logic and orchestration.
- **Repositories** → data access and persistence.
- **Models** → data shapes and validation.
- **Tasks** → scheduled background jobs.
- Never mix layers — a router must not execute SQL, and a repository must not raise `HTTPException`.
### 13.3 Single Responsibility Principle (SRP)
- A class or module should have **one and only one reason to change**.
- If a service handles both ban management *and* email notifications, split it into `BanService` and `NotificationService`.
### 13.4 Don't Repeat Yourself (DRY)
- Extract shared logic into utility functions, base classes, or dependency providers.
- If the same block of code appears in more than one place, **refactor it** into a single source of truth.
- But don't over-abstract — premature DRY that couples unrelated features is worse than a little duplication (see **Rule of Three**: refactor when something appears a third time).
### 13.5 KISS — Keep It Simple, Stupid
- Choose the simplest solution that works correctly.
- Avoid clever tricks, premature optimisation, and over-engineering.
- If a standard library function does the job, prefer it over a custom implementation.
### 13.6 YAGNI — You Aren't Gonna Need It
- Do **not** build features, abstractions, or config options "just in case".
- Implement what is required **now**. Extend later when a real need emerges.
### 13.7 Dependency Inversion Principle (DIP)
- High-level modules (services) must not depend on low-level modules (repositories) directly. Both should depend on **abstractions** (protocols / interfaces).
- Use FastAPI's `Depends()` to inject implementations — this makes swapping and testing trivial.
```python
from typing import Protocol
class BanRepository(Protocol):
async def find_ban(self, ip: str, jail: str) -> Ban | None: ...
async def save_ban(self, ban: Ban) -> None: ...
class SqliteBanRepository:
"""Concrete implementation — depends on aiosqlite."""
async def find_ban(self, ip: str, jail: str) -> Ban | None: ...
async def save_ban(self, ban: Ban) -> None: ...
```
### 13.8 Composition over Inheritance
- Favour **composing** small, focused objects over deep inheritance hierarchies.
- Use mixins or protocols only when a clear "is-a" relationship exists; otherwise, pass collaborators as constructor arguments.
### 13.9 Fail Fast
- Validate inputs as early as possible — at the API boundary with Pydantic, at service entry with assertions or domain checks.
- Raise specific exceptions immediately rather than letting bad data propagate silently.
### 13.10 Law of Demeter (Principle of Least Knowledge)
- A function should only call methods on:
1. Its own object (`self`).
2. Objects passed as parameters.
3. Objects it creates.
- Avoid long accessor chains like `request.state.db.cursor().execute(...)` — wrap them in a meaningful method.
### 13.11 Defensive Programming
- Never trust external input — validate and sanitise everything that crosses a boundary (HTTP request, file, socket, environment variable).
- Handle edge cases explicitly: empty lists, `None` values, negative numbers, empty strings.
- Use type narrowing and exhaustive pattern matching (`match` / `case`) to eliminate impossible states.
---
## 14. Quick Reference — Do / Don't
| Do | Don't |
|---|---|
| Type every function, variable, return | Leave types implicit |
| Use `async def` for I/O | Use sync functions for I/O |
| Validate with Pydantic at the boundary | Pass raw dicts through the codebase |
| Log with structlog + context keys | Use `print()` or format strings in logs |
| Write tests for every feature | Ship untested code |
| Use `aiohttp` for HTTP calls | Use `requests` |
| Handle errors with custom exceptions | Use bare `except:` |
| Keep routers thin, logic in services | Put business logic in routers |
| Use `datetime.now(datetime.UTC)` | Use naive datetimes |
| Run ruff + mypy before committing | Push code that doesn't pass linting |

272
Docs/Features.md Normal file
View File

@@ -0,0 +1,272 @@
# BanGUI — Feature List
A web application to monitor, manage, and configure fail2ban from a clean, accessible interface.
---
## 1. Setup Page
- Displayed automatically on first launch when no configuration exists.
- As long as no configuration is saved, every route redirects to the setup page.
- Once setup is complete and a configuration is saved, the setup page is never shown again and cannot be accessed.
### Options
- **Master Password** — Set a single global password that protects the entire web interface.
- **Database Path** — Define where the application stores its own SQLite database.
- **fail2ban Connection** — Specify how the application connects to the running fail2ban instance (socket path or related settings).
- **General Preferences** — Any additional application-level settings such as default time zone, date format, or session duration.
---
## 2. Login Page
- A simple password prompt with a single input field and a submit button.
- No username — only the master password set during setup.
- Every page in the application (except the setup page) requires the user to be authenticated.
- If a user is not logged in and tries to access any page, they are automatically redirected to the login page.
- After entering the correct password the user is taken to the page they originally requested.
- A logout option is available from every page so the user can end their session.
---
## 3. Ban Overview (Dashboard)
The main landing page after login. Shows recent ban activity at a glance.
### Server Status Bar
- A persistent status indicator showing whether the fail2ban server is running or unreachable.
- Displays the fail2ban version, the number of active jails, and total bans across all jails.
- Shows combined statistics: total failures detected and total bans issued since the server started.
### Ban List
- A table displaying all IPs that were banned within a selected time window.
- **Columns:** Time of ban, IP address, requested URL / service, country of origin, target domain, target subdomain.
- Rows are sorted by time, newest first.
- A time-range selector with quick presets:
- Last 24 hours
- Last 7 days (week)
- Last 30 days (month)
- Last 365 days (year)
### Access List
- A secondary view (tab or toggle) on the same page showing **all recorded accesses**, not just bans.
- Uses the same table format: time, IP address, requested URL, country, domain, subdomain.
- Shares the same time-range presets so the user can compare total traffic against banned traffic for the same period.
---
## 4. World Map View
A geographical overview of ban activity.
### Map
- A full world map rendered with country outlines only (no fill colours, no satellite imagery).
- For every country that has at least one banned IP in the selected time range, the total count is displayed centred inside that country's borders.
- Countries with zero banned IPs show no number and no label — they remain blank.
- Time-range selector with the same quick presets:
- Last 24 hours
- Last 7 days
- Last 30 days
- Last 365 days
### Access List (Map context)
- A companion table below or beside the map listing all accesses for the selected time range.
- Same columns as the Ban Overview tables: time, IP, URL, country, domain, subdomain.
- Selecting a country on the map filters the table to show only entries from that country.
---
## 5. Jail Management
A dedicated view for managing fail2ban jails and taking manual ban actions.
### Jail Overview
- A list of all jails showing their name, current status (running / stopped / idle), backend type, and key metrics.
- For each jail: number of currently banned IPs, total bans since start, current failures detected, and total failures.
- Quick indicators for the jail's find time, ban time, and max retries.
### Jail Detail
- Selecting a jail opens a detailed view with all of its settings.
- Shows every monitored log file path attached to that jail.
- Shows all fail regex and ignore regex patterns in a readable list.
- Shows the date pattern and log encoding used for parsing.
- Shows all actions attached to the jail and their configuration.
- Shows ban-time escalation settings if incremental banning is enabled (factor, formula, multipliers, max time).
### Jail Controls
- Start or stop individual jails.
- Toggle a jail into idle mode (pauses monitoring without fully stopping it) and back.
- Reload a single jail to pick up configuration changes without restarting the entire server.
- Reload all jails at once.
### Ban an IP
- Input field to enter an IP address.
- Option to select which jail the ban should apply to.
- Confirm and execute the ban.
- Visual feedback confirming the IP has been banned successfully.
### Unban an IP
- Input field to enter an IP address, or select from the list of currently banned IPs.
- Option to select the jail from which the IP should be unbanned, or unban from all jails.
- Option to unban all IPs at once across every jail.
- Confirm and execute the unban.
- Visual feedback confirming the IP has been unbanned successfully.
### Currently Banned IPs
- A quick-reference list of all IPs that are currently banned across all jails.
- Each entry shows the IP, the jail it belongs to, when the ban started, and when it will expire (if applicable).
- Shows how many times this IP has been banned before (ban count / repeat offender indicator).
- Direct unban button next to each entry for convenience.
### IP Lookup
- Enter any IP address to check whether it is currently banned, and if so in which jails.
- Show the ban history for that IP: how many times it was banned, when each ban occurred, and from which jails.
- Display enriched IP information: country, ASN (network operator), and Regional Internet Registry (RIR).
### IP Whitelist (Ignore List)
- View the list of IP addresses or networks that are excluded from banning, per jail and globally.
- Add an IP address or network range to a jail's ignore list so it will never be banned.
- Remove an IP from the ignore list.
- Toggle the "ignore self" option per jail, which automatically excludes the server's own IP addresses.
---
## 6. Configuration View
A page to inspect and modify the fail2ban configuration without leaving the web interface.
### View Configuration
- Display all active fail2ban jails and their current settings.
- For each jail, show the associated filter and its regex patterns in a readable format.
- Show global fail2ban settings (ban time, find time, max retries, etc.).
### Edit Configuration
- Inline editing of jail parameters (ban time, max retries, enabled/disabled, etc.).
- Inline editing of filter regex patterns.
- Add or remove fail regex and ignore regex patterns per jail.
- Edit the prefix regex used for pre-filtering log lines.
- Configure the date pattern and log time zone for each jail.
- Configure DNS resolution mode per jail (resolve all hostnames, IP only, etc.).
- Configure ban-time escalation: enable incremental banning and set factor, formula, multipliers, maximum ban time, and random jitter.
- Save changes and optionally reload fail2ban to apply them immediately.
- Validation feedback if a regex pattern or setting value is invalid before saving.
### Add Log Observation
- Option to register additional log files that fail2ban should monitor.
- For each new log, specify:
- The path to the log file.
- One or more regex patterns that define what constitutes a failure.
- The jail name and basic jail settings (ban time, retries, etc.).
- Choose whether the file should be read from the beginning or only new lines (head vs. tail).
- Preview matching lines from the log against the provided regex before saving, so the user can verify the pattern works.
### Regex Tester
- Paste or type a sample log line into a text field.
- Enter a fail regex pattern.
- Immediately see whether the pattern matches the sample, with the matched groups highlighted.
- Useful for crafting and debugging new filter rules before applying them to a live jail.
### Server Settings
- View and change the fail2ban log level (e.g. Critical, Error, Warning, Info, Debug).
- View and change the log target (file path, stdout, stderr, syslog, systemd journal).
- View and change the syslog socket if syslog is used.
- Flush and re-open log files (useful after log rotation).
- View and change the fail2ban database file location.
- Set the database purge age — how long historical ban records are kept before automatic cleanup.
- Set the maximum number of log-line matches stored per ban record in the database.
---
## 7. Ban History
A view for exploring historical ban data stored in the fail2ban database.
### History Table
- Browse all past bans across all jails, not just the currently active ones.
- **Columns:** Time of ban, IP address, jail, ban duration, ban count (how many times this IP was banned), country.
- Filter by jail, by IP address, or by time range.
- See at a glance which IPs are repeat offenders (high ban count).
### Per-IP History
- Select any IP to see its full ban timeline: every ban event, which jail triggered it, when it started, and how long it lasted.
- Merged view showing total failures and matched log lines aggregated across all bans for that IP.
---
## 8. External Blocklist Importer
Automated downloading and applying of external IP blocklists to block known malicious IPs on a recurring schedule.
### Blocklist Sources
- Manage a list of external blocklist URLs (e.g. `https://lists.blocklist.de/lists/all.txt`).
- Add, edit, or remove blocklist source URLs through the web interface.
- Each source has a name, URL, and an enabled/disabled toggle.
- Support for plain-text lists with one IP address per line.
- Preview the contents of a blocklist URL before enabling it (download and display a sample of entries).
### Schedule
- Configure when the blocklist import runs using a simple time-and-frequency picker (no raw cron syntax required).
- Default schedule: daily at 03:00 (server local time).
- Available frequency presets:
- Every X hours
- Daily at a specific time
- Weekly on a specific day and time
- Option to run an import manually at any time via a "Run Now" button.
- Show the date and time of the last successful import and the next scheduled run.
### Import Behaviour
- On each scheduled run, download all enabled blocklist sources.
- Validate that each downloaded entry is a well-formed IP address or CIDR range before applying it.
- Apply downloaded IPs as bans through fail2ban (preferred) or directly via an iptables chain, depending on configuration.
- If using an iptables chain: flush the chain before re-populating it so stale entries are removed automatically.
- If using fail2ban: ban each IP in a dedicated jail created for blocklist imports so they are tracked separately from regular bans.
- Skip empty lines and malformed entries gracefully instead of aborting the entire import.
- Clean up temporary downloaded files after processing.
### Import Log
- Keep a log of every import run: timestamp, source URL, number of IPs imported, number of entries skipped (invalid), and any errors.
- Display the import log in the web interface, filterable by source and date range.
- Show a warning badge in the navigation if the most recent import encountered errors.
### Error Handling
- If a blocklist URL is unreachable, log the error and continue with remaining sources.
- If curl (or the download mechanism) is unavailable, surface a clear error in the import log.
- Notify the user (via the UI status bar) when a scheduled import fails so it does not go unnoticed.
---
## 9. General Behaviour
- **Responsive layout** — Usable on desktop and tablet screens.
- **Session persistence** — The user stays logged in until they explicitly log out or the session expires.
- **Consistent navigation** — A sidebar or top navigation bar is visible on every page, providing quick access to all sections: Dashboard, World Map, Jails, Configuration, History, and Logout.
- **Time zone awareness** — All displayed times respect the time zone configured during setup.
- **Connection health** — The application continuously checks whether the fail2ban server is reachable and shows a clear warning when the connection is lost.

228
Docs/Instructions.md Normal file
View File

@@ -0,0 +1,228 @@
# AI Agent — General Instructions
You are an autonomous coding agent working on **BanGUI**, a web application for monitoring, managing, and configuring fail2ban through a clean web interface. This document defines how you operate, what rules you follow, and which workflow you repeat for every task.
Read this document completely before starting any work.
---
## 1. Project Context
BanGUI consists of two main parts:
| Layer | Stack | Docs |
|---|---|---|
| **Backend** | Python 3.12+, FastAPI, Pydantic v2, aiosqlite, structlog | [Backend-Development.md](Backend-Development.md) |
| **Frontend** | TypeScript, React, Fluent UI v9, Vite | [Web-Development.md](Web-Development.md) |
Supporting documentation you must know and respect:
| Document | Purpose |
|---|---|
| [Features.md](Features.md) | Complete feature list and expected behaviour |
| [Architekture.md](Architekture.md) | System architecture, component relationships, data flow |
| [Web-Design.md](Web-Design.md) | Visual design rules, theming, layout, spacing, motion |
| [Backend-Development.md](Backend-Development.md) | Backend coding rules, project structure, conventions |
| [Web-Development.md](Web-Development.md) | Frontend coding rules, project structure, conventions |
**Always** consult the relevant document before writing code. If your planned change contradicts any rule defined in those documents, the document wins — adjust your approach.
---
## 2. General Rules
### 2.1 Follow the Docs
- Every coding convention, naming rule, project structure decision, and library choice is defined in the development docs. Do not deviate.
- Backend code follows [Backend-Development.md](Backend-Development.md) — strict typing, async only, structlog, Pydantic models, layered architecture (routers → services → repositories).
- Frontend code follows [Web-Development.md](Web-Development.md) — strict TypeScript, Fluent UI v9 only, `makeStyles` for styling, typed API calls, hooks for state.
- Visual decisions follow [Web-Design.md](Web-Design.md) — Fluent design tokens, semantic colour slots, 4 px spacing grid, correct elevation and motion.
### 2.2 Write Production-Quality Code
- Write code as if it ships today. No TODOs, no placeholders, no half-implementations.
- Every function has explicit type annotations (Python) or type signatures (TypeScript).
- Every public function has a docstring (Python — Google style) or JSDoc comment (TypeScript).
- No `any` in TypeScript. No `Any` in Python (unless justified with a comment).
- No magic numbers or strings — use named constants.
- No dead code, no commented-out blocks, no unused imports.
### 2.3 Keep It Small and Focused
- One function does one thing.
- One component per file.
- One service per domain.
- If a file grows beyond ~150 lines (components) or ~200 lines (services), split it.
### 2.4 Never Break Existing Code
- Before changing any file, understand what it does and who depends on it.
- Run the existing test suite before and after your changes. If tests fail after your change, fix them before moving on.
- Do not remove or rename public APIs without updating all callers.
### 2.5 Think Before You Code
- Read the task description carefully. If it is ambiguous, check [Features.md](Features.md) and [Architekture.md](Architekture.md) for clarification.
- Plan your changes before writing code. Identify which files are affected, which layers are involved, and what tests are needed.
- Prefer the simplest correct solution. Do not over-engineer.
---
## 3. Task Workflow
Repeat the following cycle for every task. Do not skip steps.
### Step 1 — Pick a Task
- Open `tasks.md` and pick the next unfinished task (highest priority first).
- Mark the task as **in progress**.
- Read the task description thoroughly. Understand the expected outcome before proceeding.
### Step 2 — Plan Your Steps
- Break the task into concrete implementation steps.
- Identify which files need to be created, modified, or deleted.
- Identify which layers are affected (router, service, repository, model, component, hook, page, type, etc.).
- Identify edge cases and error scenarios.
- Write down your plan before touching any code.
### Step 3 — Write Code
- Implement the feature or fix following the plan.
- Follow all rules from the relevant development docs:
- Backend → [Backend-Development.md](Backend-Development.md)
- Frontend → [Web-Development.md](Web-Development.md)
- Design → [Web-Design.md](Web-Design.md)
- Architecture → [Architekture.md](Architekture.md)
- Write clean, well-structured, fully typed code.
- Keep commits atomic — one logical change per commit.
### Step 4 — Add Logging
- Add structured log statements at key points in new or modified code.
- Backend: use **structlog** with contextual key-value pairs — never `print()`.
- Log at appropriate levels: `info` for operational events, `warning` for recoverable issues, `error` for failures.
- Never log sensitive data (passwords, tokens, session IDs).
### Step 5 — Write Tests
- Write tests for every new or changed piece of functionality.
- Backend: use `pytest` + `pytest-asyncio` + `httpx.AsyncClient`. See [Backend-Development.md § 9](Backend-Development.md).
- Frontend: test components and hooks according to the frontend test setup.
- Test the happy path **and** error/edge cases.
- Mock external dependencies — tests must never touch real infrastructure.
- Follow the naming pattern: `test_<unit>_<scenario>_<expected>`.
### Step 6 — Review Your Code
Run a thorough self-review before considering the task done. Check **all** of the following:
#### 6.1 — Warnings and Errors
- Backend: run `ruff check` and `mypy --strict` (or `pyright --strict`). Fix every warning and error.
- Frontend: run `tsc --noEmit` and `eslint`. Fix every warning and error.
- Zero warnings, zero errors — no exceptions.
#### 6.2 — Test Coverage
- Run the test suite with coverage enabled.
- Aim for **>80 % line coverage** overall.
- Critical paths (auth, banning, scheduling, API endpoints) must be **100 %** covered.
- If coverage is below the threshold, write additional tests before proceeding.
#### 6.3 — Coding Principles
Verify your code against the coding principles defined in [Backend-Development.md § 13](Backend-Development.md) and [Web-Development.md](Web-Development.md):
- [ ] **Clean Code** — Meaningful names, small functions, no magic values, guard clauses over deep nesting.
- [ ] **Separation of Concerns** — Each module has a single, well-defined responsibility. Layers are not mixed.
- [ ] **Single Responsibility Principle** — Every class and function has one reason to change.
- [ ] **DRY** — No duplicated logic. Shared behaviour is extracted.
- [ ] **KISS** — The simplest correct solution is used. No over-engineering.
- [ ] **Type Safety** — All types are explicit. No `any` / `Any`. No `# type: ignore` without justification.
#### 6.4 — Architecture Compliance
Verify against [Architekture.md](Architekture.md) and the project structure rules:
- [ ] Files are in the correct directories (routers in `routers/`, services in `services/`, components in `components/`, etc.).
- [ ] Dependencies flow in the right direction (routers → services → repositories; pages → components → hooks).
- [ ] No circular imports.
- [ ] No business logic in routers or components.
- [ ] No HTTP/framework concerns in services or repositories.
- [ ] Pydantic models separate request, response, and domain shapes.
- [ ] Frontend types live in `types/`, not scattered across components.
### Step 7 — Update Documentation
- If your change introduces new features, new endpoints, new components, or changes existing behaviour, update the relevant docs:
- [Features.md](Features.md) — if feature behaviour changed.
- [Architekture.md](Architekture.md) — if new modules, services, or data flows were added.
- [Backend-Development.md](Backend-Development.md) or [Web-Development.md](Web-Development.md) — if new conventions were established.
- Keep documentation accurate and in sync with the code. Outdated docs are worse than no docs.
### Step 8 — Mark Task Complete
- Open `tasks.md` and mark the task as **done**.
- Add a brief summary of what was implemented or changed.
### Step 9 — Commit
- Stage all changed files.
- Write a commit message in **imperative tense**, max 72 characters for the subject line.
- Good: `Add jail reload endpoint`
- Bad: `added stuff` / `WIP` / `fix`
- If the change is large, include a body explaining **why**, not just **what**.
- Branch naming: `feature/<short-description>`, `fix/<short-description>`, `chore/<short-description>`.
- Ensure the commit passes: linter, type checker, all tests.
### Step 10 — Next Task
- Return to **Step 1** and pick the next task.
---
## 4. Workflow Summary
```
┌─────────────────────────────────────────┐
│ 1. Pick task from tasks.md │
│ 2. Plan your steps │
│ 3. Write code │
│ 4. Add logging │
│ 5. Write tests │
│ 6. Review your code │
│ ├── 6.1 Check warnings & errors │
│ ├── 6.2 Check test coverage │
│ ├── 6.3 Check coding principles │
│ └── 6.4 Check architecture │
│ 7. Update documentation if needed │
│ 8. Mark task complete in tasks.md │
│ 9. Git commit │
│ 10. Pick next task ──────── loop ───┐ │
│ ▲ │ │
│ └───────────────────────────┘ │
└─────────────────────────────────────────┘
```
---
## 5. When You Are Stuck
- Re-read the task description and the relevant docs.
- Search the existing codebase for similar patterns — follow established conventions.
- Check the fail2ban source code in `fail2ban-master/` if you need to understand how fail2ban works internally.
- If a decision is genuinely ambiguous and no document covers it, choose the simplest option that is consistent with existing code and document your reasoning in a code comment.
---
## 6. What You Must Never Do
- **Never** commit code that does not compile or has type errors.
- **Never** commit code without tests.
- **Never** use libraries that are explicitly forbidden in the development docs.
- **Never** bypass the linter or type checker with blanket ignores.
- **Never** hard-code secrets, passwords, or tokens.
- **Never** push directly to `main` — always use feature branches.
- **Never** skip the review step — sloppy code compounds over time.
- **Never** leave a task half-done — finish it or revert it.

409
Docs/Tasks.md Normal file
View File

@@ -0,0 +1,409 @@
# BanGUI — Task List
This document breaks the entire BanGUI project into development stages, ordered so that each stage builds on the previous one. Every task is described in prose with enough detail for a developer to begin work. References point to the relevant documentation.
---
## Stage 1 — Project Scaffolding
Everything in this stage is about creating the project skeleton — folder structures, configuration files, and tooling — so that development can begin on solid ground. No application logic is written here.
### 1.1 Initialise the backend project
Create the `backend/` directory with the full folder structure defined in [Backend-Development.md § 3](Backend-Development.md). Set up `pyproject.toml` with all required dependencies (FastAPI, Pydantic v2, aiosqlite, aiohttp, APScheduler 4.x, structlog, pydantic-settings) and dev dependencies (pytest, pytest-asyncio, httpx, ruff, mypy). Configure ruff for 120-character line length and double-quote strings. Configure mypy in strict mode. Add a `.env.example` with placeholder keys for `BANGUI_DATABASE_PATH`, `BANGUI_FAIL2BAN_SOCKET`, and `BANGUI_SESSION_SECRET`. Make sure the bundled fail2ban client at `./fail2ban-master` is importable by configuring the path in `pyproject.toml` or a startup shim as described in [Backend-Development.md § 2](Backend-Development.md).
### 1.2 Initialise the frontend project
Scaffold a Vite + React + TypeScript project inside `frontend/`. Install `@fluentui/react-components`, `@fluentui/react-icons`, and `react-router-dom`. Set up `tsconfig.json` with `"strict": true`. Configure ESLint with `@typescript-eslint`, `eslint-plugin-react-hooks`, and `eslint-config-prettier`. Add Prettier with the project defaults. Create the directory structure from [Web-Development.md § 4](Web-Development.md): `src/api/`, `src/components/`, `src/hooks/`, `src/layouts/`, `src/pages/`, `src/providers/`, `src/theme/`, `src/types/`, `src/utils/`. Create a minimal `App.tsx` that wraps the application in `<FluentProvider>` and `<BrowserRouter>` as shown in [Web-Development.md § 5](Web-Development.md).
### 1.3 Set up the Fluent UI custom theme
Create the light and dark brand-colour themes inside `frontend/src/theme/`. Follow the colour rules in [Web-Design.md § 2](Web-Design.md): use the Fluent UI Theme Designer to generate a brand ramp, ensure the primary colour meets the 4.5 : 1 contrast ratio, and export both `lightTheme` and `darkTheme`. Wire the theme into `App.tsx` via the `FluentProvider` `theme` prop.
### 1.4 Create the central API client
Build the typed API client in `frontend/src/api/client.ts`. It should be a thin wrapper around `fetch` that returns typed responses, includes credentials, and throws a custom `ApiError` on non-OK responses. Define the `BASE_URL` from `import.meta.env.VITE_API_URL` with a fallback to `"/api"`. Create `frontend/src/api/endpoints.ts` for path constants. See [Web-Development.md § 3](Web-Development.md) for the pattern.
### 1.5 Create the FastAPI application factory
Implement `backend/app/main.py` with the `create_app()` factory function. Register the async lifespan context manager that opens the aiosqlite database connection, creates a shared `aiohttp.ClientSession`, and initialises the APScheduler instance on startup, then closes all three on shutdown. Store these on `app.state`. Register a placeholder router so the app can start and respond to a health-check request. See [Backend-Development.md § 6](Backend-Development.md) and [Architekture.md § 2](Architekture.md) for details.
### 1.6 Create the Pydantic settings model
Implement `backend/app/config.py` using pydantic-settings. Define the `Settings` class with fields for `database_path`, `fail2ban_socket`, `session_secret`, `session_duration_minutes`, and `timezone`. Load from environment variables prefixed `BANGUI_` and from `.env`. Validate at startup — the app must fail fast with a clear error if required values are missing. See [Backend-Development.md § 11](Backend-Development.md).
### 1.7 Set up the application database schema
Design and create the SQLite schema for BanGUI's own data. The database needs tables for application settings (key-value pairs for master password hash, database path, fail2ban socket path, preferences), sessions (token, created-at, expires-at), blocklist sources (name, URL, enabled flag), and import log entries (timestamp, source URL, IPs imported, IPs skipped, errors). Write an initialisation function that creates these tables on first run via aiosqlite. This schema is for BanGUI's internal state — it does not replace the fail2ban database. See [Architekture.md § 2.2](Architekture.md) for the repository breakdown.
### 1.8 Write the fail2ban socket client wrapper
Implement `backend/app/utils/fail2ban_client.py` — an async wrapper around the fail2ban Unix domain socket protocol. Study `./fail2ban-master/fail2ban/client/csocket.py` and `./fail2ban-master/fail2ban/client/fail2banclient.py` to understand the wire protocol (pickle-based command/response). The wrapper should provide async methods for sending commands and receiving responses, handle connection errors gracefully, and log every interaction with structlog. This module is the single point of contact between BanGUI and the fail2ban daemon. See [Backend-Development.md § 2 (fail2ban Client Usage)](Backend-Development.md) and [Architekture.md § 2.2 (Utils)](Architekture.md).
---
## Stage 2 — Authentication & Setup Flow
This stage implements the very first user experience: the setup wizard that runs on first launch and the login system that protects every subsequent visit. All other features depend on these being complete.
### 2.1 Implement the setup service and repository
Build `backend/app/services/setup_service.py` and `backend/app/repositories/settings_repo.py`. The setup service accepts the initial configuration (master password, database path, fail2ban socket path, general preferences), hashes the password with a secure algorithm (e.g. bcrypt or argon2), and persists everything through the settings repository. It must enforce the one-time-only rule: once a configuration is saved, setup cannot run again. Add a method to check whether setup has been completed (i.e. whether any configuration exists in the database). See [Features.md § 1](Features.md).
### 2.2 Implement the setup router
Create `backend/app/routers/setup.py` with a `POST /api/setup` endpoint that accepts a Pydantic request model containing all setup fields and delegates to the setup service. If setup has already been completed, return a `409 Conflict`. Define request and response models in `backend/app/models/setup.py`.
### 2.3 Implement the setup-redirect middleware
Add middleware to the FastAPI app that checks on every incoming request whether setup has been completed. If not, redirect all requests (except those to `/api/setup` itself) to `/api/setup` with a `307 Temporary Redirect` or return a `403` with a clear message. Once setup is done, the middleware becomes a no-op. See [Features.md § 1](Features.md).
### 2.4 Implement the authentication service
Build `backend/app/services/auth_service.py`. It must verify the master password against the stored hash, create session tokens on successful login, store sessions through `backend/app/repositories/session_repo.py`, validate tokens on every subsequent request, and enforce session expiry. Sessions should be stored in the SQLite database so they survive server restarts. See [Features.md § 2](Features.md) and [Architekture.md § 2.2](Architekture.md).
### 2.5 Implement the auth router
Create `backend/app/routers/auth.py` with two endpoints: `POST /api/auth/login` (accepts a password, returns a session token or sets a cookie) and `POST /api/auth/logout` (invalidates the session). Define request and response models in `backend/app/models/auth.py`.
### 2.6 Implement the auth dependency
Create a FastAPI dependency in `backend/app/dependencies.py` that extracts the session token from the request (cookie or header), validates it through the auth service, and either returns the authenticated session or raises a `401 Unauthorized`. Every protected router must declare this dependency. See [Backend-Development.md § 4](Backend-Development.md) for the Depends pattern.
### 2.7 Build the setup page (frontend)
Create `frontend/src/pages/SetupPage.tsx`. The page should present a form with fields for the master password (with confirmation), database path, fail2ban socket path, and general preferences (timezone, date format, session duration). Use Fluent UI form components (`Input`, `Button`, `Field`, `Dropdown` for timezone). On submission, call `POST /api/setup` through the API client. Show validation errors inline. After successful setup, redirect to the login page. Create the corresponding API function in `frontend/src/api/setup.ts` and types in `frontend/src/types/setup.ts`. See [Features.md § 1](Features.md) and [Web-Design.md § 8](Web-Design.md) for component choices.
### 2.8 Build the login page (frontend)
Create `frontend/src/pages/LoginPage.tsx`. A single password input and a submit button — no username field. On submission, call `POST /api/auth/login`. On success, store the session (cookie or context) and redirect to the originally requested page or the dashboard. Show an error message on wrong password. Create `frontend/src/api/auth.ts` and `frontend/src/types/auth.ts`. See [Features.md § 2](Features.md).
### 2.9 Implement the auth context and route guard
Create `frontend/src/providers/AuthProvider.tsx` that manages authentication state (logged in / not logged in) and exposes login, logout, and session-check methods via React context. Create a route guard component that wraps all protected routes: if the user is not authenticated, redirect to the login page and remember the intended destination. After login, redirect back. See [Features.md § 2](Features.md) and [Web-Development.md § 7](Web-Development.md).
### 2.10 Write tests for setup and auth
Write backend tests covering: setup endpoint accepts valid data, setup endpoint rejects a second call, login succeeds with correct password, login fails with wrong password, protected endpoints reject unauthenticated requests, logout invalidates the session for both router and service. Use pytest-asyncio and httpx `AsyncClient` as described in [Backend-Development.md § 9](Backend-Development.md).
---
## Stage 3 — Application Shell & Navigation
With authentication working, this stage builds the persistent layout that every page shares: the navigation sidebar, the header, and the routing skeleton.
### 3.1 Build the main layout component
Create `frontend/src/layouts/MainLayout.tsx`. This is the outer shell visible on every authenticated page. It contains a fixed-width sidebar navigation (240 px, collapsing to 48 px on small screens) and a main content area. Use the Fluent UI `Nav` component for the sidebar with groups for Dashboard, World Map, Jails, Configuration, History, Blocklists, and a Logout action at the bottom. The layout must be responsive following the breakpoints in [Web-Design.md § 4](Web-Design.md). The main content area is capped at 1440 px and centred on wide screens.
### 3.2 Set up client-side routing
Configure React Router in `frontend/src/App.tsx` (or a dedicated `AppRoutes.tsx`). Define routes for every page: `/` (dashboard), `/map`, `/jails`, `/jails/:name`, `/config`, `/history`, `/blocklists`, `/setup`, `/login`. Wrap all routes except setup and login inside the auth guard from Stage 2. Use the `MainLayout` for authenticated routes. Create placeholder page components for each route so navigation works end to end.
### 3.3 Implement the logout flow
Wire the Logout button in the sidebar to call `POST /api/auth/logout`, clear the client-side session state, and redirect to the login page. The logout option must be accessible from every page as specified in [Features.md § 2](Features.md).
---
## Stage 4 — fail2ban Connection & Server Status
This stage establishes the live connection to the fail2ban daemon and surfaces its health to the user. It is a prerequisite for every data-driven feature.
### 4.1 Implement the health service
Build `backend/app/services/health_service.py`. It connects to the fail2ban socket using the wrapper from Stage 1.8, sends a `status` command, and parses the response to extract: whether the server is reachable, the fail2ban version, the number of active jails, and aggregated ban/failure counts. Expose a method that returns a structured health status object. Log connectivity changes (online → offline and vice versa) via structlog. See [Features.md § 3 (Server Status Bar)](Features.md).
### 4.2 Implement the health-check background task
Create `backend/app/tasks/health_check.py` — an APScheduler job that runs the health service probe every 30 seconds and caches the result in memory (e.g. on `app.state`). This ensures the dashboard endpoint can return fresh status without blocking on a socket call. See [Architekture.md § 2.2 (Tasks)](Architekture.md).
### 4.3 Implement the dashboard status endpoint
Create `backend/app/routers/dashboard.py` with a `GET /api/dashboard/status` endpoint that returns the cached server status (online/offline, version, jail count, total bans, total failures). Define response models in `backend/app/models/server.py`. This endpoint is lightweight — it reads from the in-memory cache populated by the health-check task.
### 4.4 Build the server status bar component (frontend)
Create `frontend/src/components/ServerStatusBar.tsx`. This persistent bar appears at the top of the dashboard (and optionally on other pages). It displays the fail2ban connection status (green badge for online, red for offline), the server version, active jail count, and total bans/failures. Use Fluent UI `Badge` and `Text` components. Poll `GET /api/dashboard/status` at a reasonable interval or on page focus. Create `frontend/src/api/dashboard.ts`, `frontend/src/types/server.ts`, and a `useServerStatus` hook.
### 4.5 Write tests for health service and dashboard
Test that the health service correctly parses a mock fail2ban status response, handles socket errors gracefully, and that the dashboard endpoint returns the expected shape. Mock the fail2ban socket — tests must never touch a real daemon.
---
## Stage 5 — Ban Overview (Dashboard)
The main landing page. This stage delivers the ban list and access list tables that give users a quick picture of recent activity.
### 5.1 Implement the ban service (list recent bans)
Build `backend/app/services/ban_service.py` with a method that queries the fail2ban database for bans within a given time range. The fail2ban SQLite database stores ban records — read them using aiosqlite (open the fail2ban DB path from settings, read-only). Return structured ban objects including IP, jail, timestamp, and any additional metadata available. See [Features.md § 3 (Ban List)](Features.md).
### 5.2 Implement the geo service
Build `backend/app/services/geo_service.py`. Given an IP address, resolve its country of origin (and optionally ASN and RIR). Use an external API via aiohttp or a local GeoIP database. Cache results to avoid repeated lookups for the same IP. The geo service is used throughout the application wherever country information is displayed. See [Features.md § 5 (IP Lookup)](Features.md) and [Architekture.md § 2.2](Architekture.md).
### 5.3 Implement the dashboard bans endpoint
Add `GET /api/dashboard/bans` to `backend/app/routers/dashboard.py`. It accepts a time-range query parameter (hours or a preset like `24h`, `7d`, `30d`, `365d`). It calls the ban service to retrieve bans in that window, enriches each ban with country data from the geo service, and returns a paginated list. Define request/response models in `backend/app/models/ban.py`.
### 5.4 Build the ban list table (frontend)
Create `frontend/src/components/BanTable.tsx` using Fluent UI `DataGrid`. Columns: time of ban, IP address (monospace), requested URL/service, country, domain, subdomain. Rows are sorted newest-first. Above the table, place a time-range selector implemented as a `Toolbar` with `ToggleButton` for the four presets (24 h, 7 d, 30 d, 365 d). Create a `useBans` hook that calls `GET /api/dashboard/bans` with the selected range. See [Features.md § 3 (Ban List)](Features.md) and [Web-Design.md § 8 (Data Display)](Web-Design.md).
### 5.5 Build the dashboard page
Create `frontend/src/pages/DashboardPage.tsx`. Compose the server status bar at the top, then a `Pivot` (tab control) switching between "Ban List" and "Access List". The Ban List tab renders the `BanTable`. The Access List tab uses the same table component but fetches all recorded accesses, not just bans. If the access list requires a separate endpoint, add `GET /api/dashboard/accesses` to the backend with the same time-range support. See [Features.md § 3](Features.md).
### 5.6 Write tests for ban service and dashboard endpoints
Test ban queries for each time-range preset, test that geo enrichment works with mocked API responses, and test that the endpoint returns the correct response shape. Verify edge cases: no bans in the selected range, an IP that fails geo lookup.
---
## Stage 6 — Jail Management
This stage exposes fail2ban's jail system through the UI — listing jails, viewing details, and executing control commands.
### 6.1 Implement the jail service
Build `backend/app/services/jail_service.py`. Using the fail2ban socket client, implement methods to: list all jails with their status and key metrics, retrieve the full detail of a single jail (log paths, regex patterns, date pattern, encoding, actions, ban-time escalation settings), start a jail, stop a jail, toggle idle mode, reload a single jail, and reload all jails. Each method sends the appropriate command through the socket wrapper and parses the response. See [Features.md § 5 (Jail Overview, Jail Detail, Jail Controls)](Features.md).
### 6.2 Implement the jails router
Create `backend/app/routers/jails.py`:
- `GET /api/jails` — list all jails with status and metrics.
- `GET /api/jails/{name}` — full detail for a single jail.
- `POST /api/jails/{name}/start` — start a jail.
- `POST /api/jails/{name}/stop` — stop a jail.
- `POST /api/jails/{name}/idle` — toggle idle mode.
- `POST /api/jails/{name}/reload` — reload a single jail.
- `POST /api/jails/reload-all` — reload all jails.
Define request/response models in `backend/app/models/jail.py`. Use appropriate HTTP status codes (404 if a jail name does not exist, 409 if a jail is already in the requested state). See [Architekture.md § 2.2 (Routers)](Architekture.md).
### 6.3 Implement ban and unban endpoints
Add to `backend/app/routers/bans.py`:
- `POST /api/bans` — ban an IP in a specified jail. Validate the IP with `ipaddress` before sending.
- `DELETE /api/bans` — unban an IP from a specific jail or all jails. Support an `unban_all` flag.
- `GET /api/bans/active` — list all currently banned IPs across all jails, with jail name, ban start time, expiry, and ban count.
Delegate to the ban service. See [Features.md § 5 (Ban an IP, Unban an IP, Currently Banned IPs)](Features.md).
### 6.4 Build the jail overview page (frontend)
Create `frontend/src/pages/JailsPage.tsx`. Display a card or table for each jail showing name, status badge (running/stopped/idle), backend type, banned count, total bans, failure counts, find time, ban time, and max retries. Each jail links to a detail view. Use Fluent UI `Card` or `DataGrid`. Create `frontend/src/api/jails.ts`, `frontend/src/types/jail.ts`, and a `useJails` hook. See [Features.md § 5 (Jail Overview)](Features.md).
### 6.5 Build the jail detail page (frontend)
Create `frontend/src/pages/JailDetailPage.tsx` — reached via `/jails/:name`. Fetch the full jail detail and display: monitored log paths, fail regex and ignore regex lists (rendered in monospace), date pattern, log encoding, attached actions and their config, and ban-time escalation settings. Include control buttons (Start, Stop, Idle, Reload) that call the corresponding API endpoints with confirmation dialogs (Fluent UI `Dialog`). See [Features.md § 5 (Jail Detail, Jail Controls)](Features.md).
### 6.6 Build the ban/unban UI (frontend)
On the Jails page (or a dedicated sub-section), add a "Ban an IP" form with an IP input field and a jail selector dropdown. Add an "Unban an IP" form with an IP input (or selection from the currently-banned list), a jail selector (or "all jails"), and an "unban all" option. Show success/error feedback using Fluent UI `MessageBar` or `Toast`. Build a "Currently Banned IPs" table showing IP, jail, ban start, expiry, ban count, and a direct unban button per row. See [Features.md § 5 (Ban an IP, Unban an IP, Currently Banned IPs)](Features.md).
### 6.7 Implement IP lookup endpoint and UI
Add `GET /api/geo/lookup/{ip}` to `backend/app/routers/geo.py`. The endpoint checks whether the IP is currently banned (and in which jails), retrieves its ban history (count, timestamps, jails), and fetches enriched info (country, ASN, RIR) from the geo service. On the frontend, create an IP Lookup section in the Jails area where the user can enter any IP and see all this information. See [Features.md § 5 (IP Lookup)](Features.md).
### 6.8 Implement the ignore list (whitelist) endpoints and UI
Add endpoints to `backend/app/routers/jails.py` for managing ignore lists:
- `GET /api/jails/{name}/ignoreip` — get the ignore list for a jail.
- `POST /api/jails/{name}/ignoreip` — add an IP or network to a jail's ignore list.
- `DELETE /api/jails/{name}/ignoreip` — remove an IP from the ignore list.
- `POST /api/jails/{name}/ignoreself` — toggle the "ignore self" option.
On the frontend, add an "IP Whitelist" section to the jail detail page showing the ignore list with add/remove controls. See [Features.md § 5 (IP Whitelist)](Features.md).
### 6.9 Write tests for jail and ban features
Test jail listing with mocked socket responses, jail detail parsing, start/stop/reload commands, ban and unban execution, currently-banned list retrieval, IP lookup with and without ban history, and ignore list operations. Ensure all socket interactions are mocked.
---
## Stage 7 — Configuration View
This stage lets users inspect and edit fail2ban configuration directly from the web interface.
### 7.1 Implement the config service
Build `backend/app/services/config_service.py`. It reads the active fail2ban configuration by querying the daemon for jail settings, filter regex patterns, and global parameters. It also writes configuration changes by sending the appropriate set commands through the socket (or by editing config files and triggering a reload, depending on what fail2ban supports for each setting). The service must validate regex patterns before applying them — attempting to compile each pattern and returning a clear error if it is invalid. See [Features.md § 6 (View Configuration, Edit Configuration)](Features.md).
### 7.2 Implement the config router
Create `backend/app/routers/config.py`:
- `GET /api/config/jails` — list all jails with their current configuration.
- `GET /api/config/jails/{name}` — full configuration for a single jail (filter, regex, dates, actions, escalation).
- `PUT /api/config/jails/{name}` — update a jail's configuration (ban time, max retries, enabled, regex patterns, date pattern, DNS mode, escalation settings).
- `GET /api/config/global` — global fail2ban settings.
- `PUT /api/config/global` — update global settings.
- `POST /api/config/reload` — reload fail2ban to apply changes.
Define models in `backend/app/models/config.py`. Return validation errors before saving. See [Architekture.md § 2.2 (Routers)](Architekture.md).
### 7.3 Implement log observation endpoints
Add endpoints for registering new log files that fail2ban should monitor. The user needs to specify a log file path, one or more failure-detection regex patterns, a jail name, and basic jail settings. Include a preview endpoint that reads the specified log file and tests the provided regex against its contents, returning matching lines so the user can verify the pattern before saving. See [Features.md § 6 (Add Log Observation)](Features.md).
### 7.4 Implement the regex tester endpoint
Add `POST /api/config/regex-test` to the config router. It accepts a sample log line and a fail regex pattern, attempts to match them, and returns whether the pattern matched along with any captured groups highlighted by position. This is a stateless utility endpoint. See [Features.md § 6 (Regex Tester)](Features.md).
### 7.5 Implement server settings endpoints
Create `backend/app/routers/server.py`:
- `GET /api/server/settings` — current log level, log target, syslog socket, DB path, purge age, max matches.
- `PUT /api/server/settings` — update server-level settings.
- `POST /api/server/flush-logs` — flush and re-open log files.
Delegate to `backend/app/services/server_service.py`. See [Features.md § 6 (Server Settings)](Features.md).
### 7.6 Build the configuration page (frontend)
Create `frontend/src/pages/ConfigPage.tsx`. The page should show all jails with their current settings in a readable format. Each jail section expands to show filter regex, ignore regex, date pattern, actions, and escalation settings. Provide inline editing: clicking a value turns it into an editable field. Add/remove buttons for regex patterns. A "Save" button persists changes and optionally triggers a reload. Show validation errors inline. Use Fluent UI `Accordion`, `Input`, `Textarea`, `Switch`, and `Button`. See [Features.md § 6](Features.md) and [Web-Design.md](Web-Design.md).
### 7.7 Build the regex tester UI (frontend)
Add a "Regex Tester" section to the configuration page (or as a dialog/panel). Two input fields: one for a sample log line, one for the regex pattern. On every change (debounced), call the regex-test endpoint and display the result — whether it matched, and highlight the matched groups. Use monospace font for both inputs. See [Features.md § 6 (Regex Tester)](Features.md).
### 7.8 Build the server settings UI (frontend)
Add a "Server Settings" section to the configuration page. Display current values for log level, log target, syslog socket, DB path, purge age, and max matches. Provide dropdowns for log level and log target, text inputs for paths and numeric values. Include a "Flush Logs" button. See [Features.md § 6 (Server Settings)](Features.md).
### 7.9 Write tests for configuration features
Test config read and write operations with mocked fail2ban responses, regex validation (valid and invalid patterns), the regex tester with matching and non-matching inputs, and server settings read/write. Verify that changes are only applied after validation passes.
---
## Stage 8 — World Map View
A geographical visualisation of ban activity. This stage depends on the geo service from Stage 5 and the ban data pipeline from Stage 5.
### 8.1 Implement the map data endpoint
Add `GET /api/dashboard/bans/by-country` to the dashboard router. It accepts the same time-range parameter as the ban list endpoint. It queries bans in the selected window, enriches them with geo data, and returns an aggregated count per country (ISO country code → ban count). Also return the full ban list so the frontend can display the companion table. See [Features.md § 4](Features.md).
### 8.2 Build the world map component (frontend)
Create `frontend/src/components/WorldMap.tsx`. Render a full world map with country outlines only — no fill colours, no satellite imagery. For each country with bans, display the ban count centred inside the country's borders. Countries with zero bans remain blank. Consider a lightweight SVG-based map library or a TopoJSON/GeoJSON world outline rendered with D3 or a comparable tool. The map must be interactive: clicking a country filters the companion access list. Include the same time-range selector as the dashboard. See [Features.md § 4](Features.md).
### 8.3 Build the map page (frontend)
Create `frontend/src/pages/MapPage.tsx`. Compose the time-range selector, the `WorldMap` component, and an access list table below. When a country is selected on the map, the table filters to show only entries from that country. Clicking the map background (or a "Clear filter" button) removes the country filter. Create `frontend/src/hooks/useMapData.ts` to fetch and manage the aggregated data. See [Features.md § 4](Features.md).
### 8.4 Write tests for the map data endpoint
Test aggregation correctness: multiple bans from the same country should be summed, unknown countries should be handled gracefully, and empty time ranges should return an empty map object.
---
## Stage 9 — Ban History
This stage exposes historical ban data from the fail2ban database for forensic exploration.
### 9.1 Implement the history service
Build `backend/app/services/history_service.py`. Query the fail2ban database for all past ban records (not just currently active ones). Support filtering by jail, IP address, and time range. Compute ban count per IP to identify repeat offenders. Provide a per-IP timeline method that returns every ban event for a given IP: which jail triggered it, when it started, how long it lasted, and any matched log lines stored in the database. See [Features.md § 7](Features.md).
### 9.2 Implement the history router
Create `backend/app/routers/history.py`:
- `GET /api/history` — paginated list of all historical bans with filters (jail, IP, time range). Returns time, IP, jail, duration, ban count, country.
- `GET /api/history/{ip}` — per-IP detail: full ban timeline, total failures, matched log lines.
Define models in `backend/app/models/history.py`. Enrich results with geo data. See [Architekture.md § 2.2](Architekture.md).
### 9.3 Build the history page (frontend)
Create `frontend/src/pages/HistoryPage.tsx`. Display a `DataGrid` table of all past bans with columns for time, IP (monospace), jail, ban duration, ban count, and country. Add filter controls above the table: a jail dropdown, an IP search input, and the standard time-range selector. Highlight rows with high ban counts to flag repeat offenders. Clicking an IP row navigates to a per-IP detail view showing the full ban timeline and aggregated failures. See [Features.md § 7](Features.md).
### 9.4 Write tests for history features
Test history queries with various filters, per-IP timeline construction, ban count computation, and edge cases (IP with no history, jail that no longer exists).
---
## Stage 10 — External Blocklist Importer
This stage adds the ability to automatically download and apply external IP blocklists on a schedule.
### 10.1 Implement the blocklist repository
Build `backend/app/repositories/blocklist_repo.py` and `backend/app/repositories/import_log_repo.py`. The blocklist repo persists blocklist source definitions (name, URL, enabled flag) in the application database. The import log repo records every import run with timestamp, source URL, IPs imported, IPs skipped, and any errors encountered. See [Architekture.md § 2.2 (Repositories)](Architekture.md).
### 10.2 Implement the blocklist service
Build `backend/app/services/blocklist_service.py`. It manages blocklist source CRUD (add, edit, remove, toggle enabled). For the actual import: download each enabled source URL via aiohttp, validate every entry as a well-formed IP or CIDR range using the `ipaddress` module, skip malformed lines gracefully, and apply valid IPs as bans through fail2ban (in a dedicated blocklist jail) or via iptables. If using iptables, flush the chain before re-populating. Log every step with structlog. Record import results through the import log repository. Handle unreachable URLs by logging the error and continuing with remaining sources. See [Features.md § 8](Features.md).
### 10.3 Implement the blocklist import scheduled task
Create `backend/app/tasks/blocklist_import.py` — an APScheduler job that runs the blocklist service import at the configured schedule. The default is daily at 03:00. The schedule should be configurable through the blocklist service (saved in the app database). See [Features.md § 8 (Schedule)](Features.md).
### 10.4 Implement the blocklist router
Create `backend/app/routers/blocklist.py`:
- `GET /api/blocklists` — list all blocklist sources with their status.
- `POST /api/blocklists` — add a new source.
- `PUT /api/blocklists/{id}` — edit a source (name, URL, enabled).
- `DELETE /api/blocklists/{id}` — remove a source.
- `GET /api/blocklists/{id}/preview` — download and display a sample of the blocklist contents.
- `POST /api/blocklists/import` — trigger a manual import immediately ("Run Now").
- `GET /api/blocklists/schedule` — get the current schedule and next run time.
- `PUT /api/blocklists/schedule` — update the schedule.
- `GET /api/blocklists/log` — paginated import log, filterable by source and date range.
Define models in `backend/app/models/blocklist.py`. See [Architekture.md § 2.2](Architekture.md).
### 10.5 Build the blocklist management page (frontend)
Create `frontend/src/pages/BlocklistPage.tsx`. Display a list of blocklist sources as cards or rows showing name, URL, enabled toggle, and action buttons (edit, delete, preview). Add a form to create or edit a source. Show the schedule configuration with a simple time-and-frequency picker (no raw cron) — dropdowns for frequency preset and a time input. Include a "Run Now" button and a display of last import time and next scheduled run. Below, show the import log as a table (timestamp, source, IPs imported, IPs skipped, errors) with filters. If the most recent import had errors, show a warning badge in the navigation. See [Features.md § 8](Features.md).
### 10.6 Write tests for blocklist features
Test source CRUD, import with valid/invalid entries, schedule update, manual import trigger, import log persistence, and error handling when a URL is unreachable. Mock all HTTP calls.
---
## Stage 11 — Polish, Cross-Cutting Concerns & Hardening
This final stage covers everything that spans multiple features or improves the overall quality of the application.
### 11.1 Implement connection health indicator
Add a persistent connection-health indicator visible on every page (part of the `MainLayout`). When the fail2ban server becomes unreachable, show a clear warning bar at the top of the interface. When it recovers, dismiss the warning. The indicator reads from the cached health status maintained by the background task from Stage 4. See [Features.md § 9](Features.md).
### 11.2 Add timezone awareness
Ensure all timestamps displayed in the frontend respect the timezone configured during setup. Store all dates in UTC on the backend. Convert to the user's configured timezone on the frontend before display. Create a `formatDate` utility in `frontend/src/utils/` that applies the configured timezone and format. See [Features.md § 9](Features.md).
### 11.3 Add responsive layout polish
Review every page against the breakpoint table in [Web-Design.md § 4](Web-Design.md). Ensure the sidebar collapses correctly on small screens, tables scroll horizontally instead of breaking, cards stack vertically, and no content overflows. Test at 320 px, 640 px, 1024 px, and 1920 px widths.
### 11.4 Add loading and error states
Every page and data-fetching component must handle three states: loading (show Fluent UI `Spinner` or skeleton shimmer), error (show a `MessageBar` with details and a retry action), and empty (show an informational message). Remove bare spinners that persist longer than one second — replace them with skeleton screens as required by [Web-Design.md § 6](Web-Design.md).
### 11.5 Implement reduced-motion support
Honour the `prefers-reduced-motion` media query. When detected, disable all non-essential animations (tab transitions, row slide-outs, panel fly-ins) and replace them with instant state changes. See [Web-Design.md § 6 (Motion Rules)](Web-Design.md).
### 11.6 Add accessibility audit
Verify WCAG 2.1 AA compliance across the entire application. All interactive elements must be keyboard-accessible. All Fluent UI components include accessibility by default, but custom components (world map, regex tester highlight) need manual `aria-label` and role attributes. Ensure colour is never the sole indicator of status — combine with icons or text labels. See [Web-Design.md § 1](Web-Design.md).
### 11.7 Add structured logging throughout
Review every service and task to confirm that all significant operations are logged with structlog and contextual key-value pairs. Log ban/unban actions, config changes, blocklist imports, authentication events, and health transitions. Never log passwords, session tokens, or other secrets. See [Backend-Development.md § 7](Backend-Development.md).
### 11.8 Add global error handling
Register FastAPI exception handlers in `main.py` that map all custom domain exceptions to HTTP status codes with structured error bodies. Ensure no unhandled exception ever returns a raw 500 with a stack trace to the client. Log all errors with full context before returning the response. See [Backend-Development.md § 8](Backend-Development.md).
### 11.9 Final test pass and coverage check
Run the full test suite. Ensure all tests pass. Check coverage: aim for over 80 % line coverage overall, with 100 % on critical paths (auth, banning, scheduled imports). Add missing tests where coverage is below threshold. Ensure `ruff`, `mypy --strict`, and `tsc --noEmit` all pass with zero errors. See [Backend-Development.md § 9](Backend-Development.md) and [Web-Development.md § 1](Web-Development.md).

406
Docs/Web-Design.md Normal file
View File

@@ -0,0 +1,406 @@
# Frontend Design — Rules & Guidelines
Rules and conventions every designer must follow when working on BanGUI. This document defines the visual language, component usage, and design principles for the entire application. Read this before creating your first mockup or writing your first style.
**Design system:** [Microsoft Fluent UI](https://developer.microsoft.com/en-us/fluentui#/get-started/web)
---
## 1. Design Philosophy
- **Clarity over decoration.** Every visual element must serve a purpose. If it does not help the user read, navigate, or act — remove it.
- **Consistency over creativity.** Reuse existing Fluent UI components and patterns before inventing new ones. A familiar interface lowers cognitive load.
- **Content first.** BanGUI is a data-heavy monitoring tool. Design around the data — tables, charts, status indicators — not around ornamental chrome.
- **Quiet until necessary.** The default state of the UI should feel calm and neutral. Reserve colour, motion, and elevation for moments that genuinely need attention (errors, warnings, active bans).
- **Accessible by default.** Every design decision must pass WCAG 2.1 AA. Colour alone must never be the only way to convey information.
---
## 2. Theming & Colour
All colour decisions go through the Fluent UI theme system. Never hard-code hex values in components.
### Theme Slots
Use **semantic colour slots** from `ISemanticColors` wherever possible. Semantic slots describe *intent* rather than *appearance*, which means the UI adapts automatically when the theme changes.
| Intent | Semantic slot | Example usage |
|---|---|---|
| Primary action | `themePrimary` | Primary buttons, active nav items, links |
| Danger / error | `errorText`, `errorIcon` | Ban warnings, failed connections, validation errors |
| Success | `successIcon` (extend with custom slot) | Successful unban confirmation, server online status |
| Warning | Shared colour `yellow` / `yellowDark` | Blocklist import warnings, approaching limits |
| Neutral text | `neutralPrimary` | Body copy, table cell text |
| Secondary text | `neutralSecondary` | Metadata, timestamps, captions |
| Disabled | `disabledText`, `disabledBackground` | Inactive controls, unavailable jails |
| Surface | `bodyBackground`, `bodyStandoutBackground` | Page canvas, sidebar, card backgrounds |
### Custom Theme
BanGUI uses a **single custom theme** generated with the [Fluent UI Theme Designer](https://aka.ms/themedesigner). The theme is defined once in code and consumed everywhere via `ThemeProvider`.
- The primary colour must have a **contrast ratio of at least 4.5 : 1** against `white` for text and **3 : 1** for large text and UI elements.
- Provide a **dark theme variant** alongside the default light theme. Both must share the same semantic slot names — only the palette values differ.
- Never reference Fluent UI palette slots (`themeDarker`, `neutralLight`, etc.) directly in components. Always go through semantic slots so theme switching works seamlessly.
### Colour Rules
- **Never use inline hex or RGB values.** Always reference theme tokens (`theme.palette.*` or `theme.semanticColors.*`).
- Use the **9-step theme colour ramp** (`themeLighterAlt` through `themeDarker`) for subtle tints and shades within the primary hue.
- Use the **14-step neutral ramp** (`white` through `black`) for backgrounds, borders, and text hierarchy.
- Reserve the **shared accent colours** (red, yellow, green, blue) strictly for semantic meaning: errors, warnings, success, informational. Never use them decoratively.
- When two adjacent regions need separation, prefer a **1 px `neutralLight` border** or a subtle background shift (`bodyStandoutBackground`) over a heavy line.
---
## 3. Typography
Use the Fluent UI type ramp exclusively. Do not introduce custom font sizes.
### Type Ramp
| Token | Size | Weight | Usage in BanGUI |
|---|---|---|---|
| `FontSizes.size28` | 28 px | Semibold (600) | Page titles — "Ban Overview", "Jail Management" |
| `FontSizes.size20` | 20 px | Semibold (600) | Section headers — "Ban List", "Server Settings" |
| `FontSizes.size16` | 16 px | Semibold (600) | Card titles, panel headers, sub-section labels |
| `FontSizes.size14` | 14 px | Regular (400) | Body text, table cell content, form labels, buttons |
| `FontSizes.size12` | 12 px | Regular (400) | Metadata: timestamps, IP geolocation tags, ban counts, tooltips |
| `FontSizes.size10` | 10 px | Regular (400) | Badges, disclaimer text, chart axis labels (use sparingly) |
### Typography Rules
- **Font family** — Use the Fluent default (`Segoe UI`, with the standard fallback stack). Never override the font family unless a monospace context demands it (log output, regex patterns, IP addresses — use `Consolas, "Courier New", monospace` for those).
- **Weight** — Only two weights in regular UI: **Regular (400)** for body text and **Semibold (600)** for headings and emphasis. Use **Bold (700)** only in exceptional data visualisation contexts.
- **Line height** — Follow the recommended line heights from the Fluent type ramp (e.g., 14 px text → 20 px line-height, 20 px text → 28 px line-height).
- **Text colour hierarchy** — Use `neutralPrimary` for primary text, `neutralSecondary` for secondary/supporting text, and `neutralTertiary` only for placeholder text.
- **Alignment** — Left-align all text by default. Centre-align only short labels inside cards or stat badges. Never right-align body text.
- **Truncation** — Long text (IP addresses, log paths, regex patterns) must truncate with an ellipsis and show the full content in a tooltip on hover.
- **Monospace contexts** — IP addresses, regex patterns, log paths, code snippets, and jail filter expressions must always render in monospace for readability.
---
## 4. Layout & Spacing
### Grid
- Use a **12-column responsive grid**. In Fluent UI React, prefer CSS Grid or `Stack` for layout rather than Fabric Core grid classes.
- The main content area sits next to a **fixed-width side navigation** (240 px collapsed to 48 px on small screens).
- Maximum content width: **1440 px**, centred on ultra-wide monitors.
### Breakpoints
Follow the Fluent UI breakpoint scale:
| Name | Range | Layout behaviour |
|---|---|---|
| Small | 320 479 px | Single column, collapsed nav, stacked cards |
| Medium | 480 639 px | Single column, optional side nav overlay |
| Large | 640 1023 px | Two columns, side nav visible |
| Extra large | 1024 1365 px | Full layout, side nav + main + optional aside |
| XX-large | 1366 1919 px | Comfortable full layout |
| XXX-large | 1920 px + | Max-width content, extra breathing room |
### Spacing Scale
Use the Fluent **4 px base unit** for all spacing. Common values:
| Token | Value | Usage |
|---|---|---|
| `s2` | 4 px | Inline spacing between icon and label |
| `s1` | 8 px | Padding inside compact elements (badges, chips) |
| `m` | 16 px | Standard padding inside cards and panels |
| `l1` | 20 px | Gap between table rows / list items |
| `l2` | 32 px | Margin between sections on a page |
| `xl` | 48 px | Top margin for page content below the header |
### Spacing Rules
- **Never use arbitrary pixel values.** Always snap to the 4 px grid (4, 8, 12, 16, 20, 24, 32, 40, 48…).
- Padding inside a card or panel: **16 px** on all sides.
- Gap between cards in a grid: **16 px**.
- Gap between a page title and the first content block: **24 px**.
- Table cell padding: **12 px horizontal**, **8 px vertical**.
---
## 5. Elevation & Depth
Use Fluent UI depth levels to communicate layering. Do not create custom `box-shadow` values.
| Level | Token | Usage in BanGUI |
|---|---|---|
| **Depth 4** | `Depths.depth4` | Cards, grid tiles, stat summaries on the dashboard |
| **Depth 8** | `Depths.depth8` | Command bars, dropdown menus, filter popups |
| **Depth 16** | `Depths.depth16` | Tooltips, hover cards (IP info popup), teaching callouts |
| **Depth 64** | `Depths.depth64` | Modal dialogs (ban/unban confirmation), side panels |
### Elevation Rules
- A surface's depth must **match its semantic importance**. A card sits at depth 4; a dialog demanding user action sits at depth 64.
- The **page canvas has zero elevation** — it is the baseline.
- Only **one modal level** may be visible at a time. Never stack dialogs.
- When a dropdown or popup opens, the rest of the interface should receive an **overlay scrim** (`rgba(0, 0, 0, 0.4)`) only for depth-64 surfaces (modals). Lighter popups (depth 816) dismiss on outside click without a scrim.
---
## 6. Motion & Animation
All animations follow Fluent motion principles. Motion should feel natural, purposeful, and quick.
### Timing
| Duration | Token | Usage |
|---|---|---|
| 100 ms | `MotionDurations.duration1` | Micro-interactions: button press, checkbox toggle |
| 200 ms | `MotionDurations.duration2` | Fade in/out of tooltips, small element transitions |
| 300 ms | `MotionDurations.duration3` | Panel slide-in, page transitions, list reordering |
| 400 ms | `MotionDurations.duration4` | Large surface entrance (full-screen modals, first-load hero) |
### Easing
| Curve | Token | When to use |
|---|---|---|
| Decelerate | `MotionTimings.decelerate` | Elements entering the view (slide in, fade in) |
| Accelerate | `MotionTimings.accelerate` | Elements leaving the view (slide out, fade out) |
| Standard | `MotionTimings.standard` | Elements that reposition within the view |
| Linear | `MotionTimings.linear` | Opacity-only transitions (fade out before a drill-in) |
### Animation Patterns
| Interaction | Pattern | Details |
|---|---|---|
| Opening a jail detail panel | **Slide right in** | Panel slides from right edge, content fades in after 100 ms delay |
| Banning / unbanning an IP | **Delete & Slide** | Row fades out (300 ms decelerate), remaining rows slide up (300 ms) |
| Switching dashboard tabs | **Tabs & Pivots** | Active indicator slides (300 ms), outgoing content slides out, incoming slides in with 100 ms delay |
| Navigating to a sub-page | **Drill In** | Old content fades out (100 ms linear), new content scales down in (300 ms decelerate) |
### Motion Rules
- **Never animate something the user did not trigger.** Auto-refreshing data should appear without animation — just update in place.
- **Respect `prefers-reduced-motion`.** When the OS or browser signals reduced motion, disable all non-essential animations and replace them with instant state changes.
- **No loading spinners longer than 1 second without explanation.** If a network call exceeds 1 s, show a skeleton screen or a contextual loading message, not just a spinner.
- Keep looping animations (pulsing status dots, progress bars) subtle and small-area. Never animate large surfaces continuously.
---
## 7. Iconography
- Use the **Fluent UI icon set** (`@fluentui/react-icons` or the Fabric Core icon font). Do not introduce third-party icon libraries.
- Icon size follows the adjacent text: **16 px** icons next to 14 px body text, **20 px** icons next to 1620 px headers.
- Icons must always have a **text label** or an `aria-label`. Icon-only buttons are acceptable only in toolbars and compact table rows, and they must have a tooltip.
- Use **outline** icon variants by default. Switch to **filled** only for active or selected states (e.g., filled star for a favourited jail).
- Icon colour inherits from the text colour of its context. Override only for semantic purposes (red icon for errors, green for success).
---
## 8. Component Usage
Use Fluent UI React components as the building blocks. The following mapping shows which component to use for each BanGUI feature area.
### Navigation
| Element | Fluent component | Notes |
|---|---|---|
| Side navigation | `Nav` | Persistent on large screens, collapsible on small. Groups: Dashboard, Map, Jails, Config, History, Blocklists. |
| Breadcrumbs | `Breadcrumb` | Show on detail pages (Jail > sshd, History > IP detail). |
| Page tabs | `Pivot` | Dashboard (Ban List / Access List), Map (Map / Access List). |
### Data Display
| Element | Fluent component | Notes |
|---|---|---|
| Data tables | `DetailsList` | All ban tables, jail overviews, history tables. Enable column sorting, selection, and shimmer loading. |
| Stat cards | `DocumentCard` or custom `Stack` card | Dashboard status bar — server status, total bans, active jails. Use `Depth 4`. |
| Status indicators | `Badge` / `Icon` + colour | Server online/offline, jail running/stopped/idle. |
| Country labels | Monospaced text + flag emoji or icon | Geo data next to IP addresses. |
### Forms & Actions
| Element | Fluent component | Notes |
|---|---|---|
| Primary actions | `PrimaryButton` | "Ban IP", "Save Configuration", "Run Import Now". |
| Secondary actions | `DefaultButton` | "Cancel", "Reset", "Clear Filters". |
| Danger actions | `PrimaryButton` with danger styling | "Unban All", "Flush Chain". Red theme override on `themePrimary`. |
| Text inputs | `TextField` | IP address entry, regex pattern input, search fields. |
| Dropdowns | `Dropdown` | Jail selector, time-range presets, log level picker. |
| Toggles | `Toggle` | Enable/disable jail, enable blocklist source, ignore-self toggle. |
| Confirmations | `Dialog` | Confirm ban, confirm unban-all, confirm delete actions. Always require explicit user action. |
### Feedback
| Element | Fluent component | Notes |
|---|---|---|
| Success messages | `MessageBar` (success) | "IP 1.2.3.4 has been banned in jail sshd." |
| Error messages | `MessageBar` (error) | "Failed to connect to fail2ban server." |
| Warning messages | `MessageBar` (warning) | "Blocklist import encountered 12 invalid entries." |
| Loading states | `Shimmer` | Apply to `DetailsList` rows and stat cards while data loads. |
| Empty states | Custom illustration + text | "No bans recorded in the last 24 hours." Centre on the content area. |
| Tooltips | `Tooltip` / `TooltipHost` | Full IP info on hover, full regex on truncated text, icon-only button labels. |
---
## 9. Tables & Data Grids
Tables are the primary UI element in BanGUI. They must be treated with extreme care.
- Use Fluent UI's `DetailsList` for all tabular data.
- **Column widths:** Give the widest anticipated content enough room. IP addresses need ~140 px, timestamps ~180 px, country codes ~80 px. Use `minWidth` and `maxWidth` on each column.
- **Row density:** Use `compact` mode for tables with many rows (ban lists, history) and `normal` mode for tables with fewer rows (jail overview, blocklist sources).
- **Sorting:** Every column with comparable data must be sortable. Default sort: newest first for time-based tables.
- **Selection:** Table rows for actionable entities (banned IPs, jails) must support single selection that highlights the row and enables contextual actions in a command bar above.
- **Shimmer loading:** When data is loading, show shimmer placeholder rows matching the expected column layout. Never show a blank table body.
- **Empty state:** When the table has zero rows, display a centred message and icon inside the table frame (e.g., "No bans in this time range").
- **Sticky header:** Table headers must stick to the top of the scrollable area so column labels are always visible.
- **Zebra striping:** Do not use alternating row colours. Fluent UI relies on hover and selection highlights instead.
- **Pagination vs. virtual scrolling:** For tables that may exceed 100 rows, use virtual scrolling (`DetailsList` supports this natively). Avoid traditional pagination.
---
## 10. Cards & Stat Blocks
The dashboard uses cards to display key figures (server status, total bans, active jails).
- Each card is a contained surface at **Depth 4** with **16 px padding** on all sides.
- Card layout: **icon or status dot** (left) + **large numeric value** (`FontSizes.size28`, semibold) + **label** (`FontSizes.size12`, `neutralSecondary`).
- Cards arrange in a horizontal row using `Stack` with `horizontal` tokens and `16 px` gap.
- On small screens, cards stack vertically in a single column.
- **Do not put actions inside stat cards.** They are read-only summaries. Actions belong in context menus or command bars.
---
## 11. World Map View
- The map renders country outlines only — **no fill colours, no satellite imagery, no terrain shading**.
- Countries with banned IPs display a **count badge** centred inside the country polygon. Use `FontSizes.size14` semibold, `themePrimary` colour.
- Countries with zero bans remain completely blank — no label, no tint.
- On hover: country region gets a subtle `neutralLighterAlt` fill. On click: fill shifts to `themeLighterAlt` and the companion table below filters to that country.
- The map must have a **light neutral border** (`neutralLight`) around its container, at **Depth 4**.
- Time-range selector above the map uses `Pivot` with quick presets (24 h, 7 d, 30 d, 365 d).
---
## 12. Forms & Inputs
- Use `TextField` with a **visible label above** the input (not a floating label).
- Every text input must show a `description` or `placeholder` that illustrates the expected format (e.g., `192.168.1.0/24`).
- Validation errors appear **below the input** using the built-in `errorMessage` prop — red text, small size (`FontSizes.size12`).
- Group related fields inside a bordered `Stack` or a `GroupedList` with a section header.
- Action buttons sit at the **bottom-right** of a form group, with primary on the right and secondary (Cancel) on the left.
- For the Regex Tester: use a side-by-side layout — sample log line on the left, regex input on the right, match result highlighted below. Monospace font for both fields.
---
## 13. Feedback & Status
### Server Status Bar
- A thin horizontal bar at the very top of the content area (below the nav header).
- **Online:** green dot + "fail2ban running — v0.11.2 — 14 jails — 231 total bans". Use `FontSizes.size12`, `neutralSecondary`.
- **Offline / unreachable:** red dot + "fail2ban server unreachable" in `errorText` colour. Bar background shifts to a very light red tint.
- This bar is **non-dismissible** and always visible.
### Inline Feedback
- After a successful action (ban, unban, save config): show a `MessageBar` of type `success` **at the top of the current content area**, auto-dismiss after 5 seconds.
- After a failed action: show a `MessageBar` of type `error`, **not auto-dismissed** — the user must close it manually.
- Warnings (import issues, validation hints) use `MessageBar` of type `warning`, not auto-dismissed.
---
## 14. Dark Theme
- Every screen must look correct in both light and dark themes.
- Design light theme first, then verify dark theme by swapping the palette in the Theme Designer.
- **Never assume white backgrounds.** Always use `bodyBackground` or `bodyStandoutBackground` from the theme.
- **Never use black text directly.** Always use `neutralPrimary`, which adapts to both themes.
- Images, illustrations, and the world map must have **transparent or theme-aware backgrounds** that do not create harsh rectangles in dark mode.
- Test contrast ratios in **both themes** — a colour that passes AA on white may fail on dark grey.
---
## 15. Accessibility
- **Colour contrast:** All text must meet WCAG 2.1 AA minimums (4.5 : 1 for normal text, 3 : 1 for large text and UI components). Use the [Fluent UI colour accessibility guide](https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/fabric-website/files/coloraccessibility_29sep2016.pdf) as reference.
- **Keyboard navigation:** Every interactive element must be reachable via Tab and operable with Enter or Space. Sidebar navigation, table row selection, dropdown menus — all must work without a mouse.
- **Focus indicators:** Use the default Fluent UI focus ring (2 px `themePrimary` outline). Never hide or override focus styles.
- **Screen readers:** Every icon-only button has an `aria-label`. Tables use `aria-sort` on sortable columns. Status indicators have `aria-live="polite"` regions so screen readers announce changes.
- **Reduced motion:** Wrap all custom animations in a `prefers-reduced-motion` media query and provide an instant fallback.
- **Touch targets:** All interactive elements have a minimum tap target of **44 x 44 px** on touch devices (achieved via padding if the visible element is smaller).
---
## 16. Design Tokens & File Organisation
- All theme definitions live in a single file: `theme/appTheme.ts`.
- All spacing, sizing, and z-index constants live in `theme/tokens.ts`.
- Components consume tokens via the theme context — never import raw pixel values.
- When a design requires a value not already in the token set, **add it to the shared tokens file** and document its purpose. Never define a one-off constant inside a component.
```ts
// theme/appTheme.ts
import { createTheme } from "@fluentui/react";
export const lightTheme = createTheme({
palette: {
themePrimary: "#0078d4",
themeDarkAlt: "#106ebe",
// ... generated via Theme Designer
},
});
export const darkTheme = createTheme({
palette: {
themePrimary: "#2b88d8",
themeDarkAlt: "#3aa0f3",
// ...
},
});
```
```ts
// theme/tokens.ts
export const spacing = {
xs: 4,
s: 8,
m: 16,
l: 24,
xl: 32,
xxl: 48,
} as const;
export const contentMaxWidth = 1440;
export const sideNavWidth = 240;
export const sideNavCollapsedWidth = 48;
```
---
## 17. Do-Not-Do List
| Do | Do Not |
|---|---|
| Use Fluent UI components for every standard control | Build custom buttons, dropdowns, or modals from scratch |
| Reference theme tokens for all colours | Hard-code hex values like `#ff0000` in components |
| Follow the 4 px spacing grid | Use arbitrary pixel values (13 px, 7 px, 19 px) |
| Provide a tooltip for every icon-only button | Leave icons unlabelled and inaccessible |
| Use `Shimmer` for loading states | Show a blank screen or a standalone spinner with no context |
| Design for both light and dark themes | Default to white backgrounds assuming light mode only |
| Use `DetailsList` for all tabular data | Use raw HTML `<table>` elements or a third-party data grid |
| Use semantic colour slots (`errorText`, `bodyBackground`) | Use descriptive palette slots (`red`, `neutralLight`) directly |
| Use `prefers-reduced-motion` for all custom animation | Force animation on users with motion sensitivities |
| Test with keyboard and screen reader before signing off | Assume mouse-only usage |
---
## 18. References
- [Fluent UI — Get Started](https://developer.microsoft.com/en-us/fluentui#/get-started/web)
- [Fluent UI — Typography](https://developer.microsoft.com/en-us/fluentui#/styles/web/typography)
- [Fluent UI — Colour Theme Slots](https://developer.microsoft.com/en-us/fluentui#/styles/web/colors/theme-slots)
- [Fluent UI — Elevation](https://developer.microsoft.com/en-us/fluentui#/styles/web/elevation)
- [Fluent UI — Layout](https://developer.microsoft.com/en-us/fluentui#/styles/web/layout)
- [Fluent UI — Motion](https://developer.microsoft.com/en-us/fluentui#/styles/web/motion)
- [Fluent UI Theme Designer](https://aka.ms/themedesigner)
- [Colour Accessibility Guide (PDF)](https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/fabric-website/files/coloraccessibility_29sep2016.pdf)
- [WCAG 2.1 AA Guidelines](https://www.w3.org/WAI/WCAG21/quickref/)

520
Docs/Web-Development.md Normal file
View File

@@ -0,0 +1,520 @@
# Frontend Development — Rules & Guidelines
Rules and conventions every frontend developer must follow. Read this before writing your first line of code.
---
## 1. Language & Typing
- **TypeScript** is mandatory — no plain JavaScript files (`.js`, `.jsx`) in the codebase.
- Use **strict mode** (`"strict": true` in `tsconfig.json`) — the project must compile with zero errors.
- Never use `any`. If a type is truly unknown, use `unknown` and narrow it with type guards.
- Prefer **interfaces** for object shapes that may be extended, **type aliases** for unions, intersections, and utility types.
- Every function must have explicit parameter types and return types — including React components (`React.FC` is discouraged; type props and return `JSX.Element` explicitly).
- Use `T | null` or `T | undefined` instead of `Optional` patterns — be explicit about nullability.
- Use `as const` for constant literals and enums where it improves type narrowness.
- Run `tsc --noEmit` in CI — the codebase must pass with zero type errors.
```tsx
// Good
interface BanEntry {
ip: string;
jail: string;
bannedAt: string;
expiresAt: string | null;
}
function BanRow({ ban }: { ban: BanEntry }): JSX.Element {
return <tr><td>{ban.ip}</td><td>{ban.jail}</td></tr>;
}
// Bad — untyped, uses `any`
function BanRow({ ban }: any) {
return <tr><td>{ban.ip}</td></tr>;
}
```
---
## 2. Reusable Types
- All **shared type definitions** live in a dedicated `types/` directory.
- Group types by domain: `types/ban.ts`, `types/jail.ts`, `types/auth.ts`, `types/api.ts`, etc.
- Import types using the `import type` syntax when the import is only used for type checking — this keeps the runtime bundle clean.
- Component-specific prop types may live in the same file as the component, but any type used by **two or more files** must move to `types/`.
- Never duplicate a type definition — define it once, import everywhere.
- Export API response shapes alongside their domain types so consumers always know what the server returns.
```ts
// types/ban.ts
export interface Ban {
ip: string;
jail: string;
bannedAt: string;
expiresAt: string | null;
banCount: number;
country: string | null;
}
export interface BanListResponse {
bans: Ban[];
total: number;
}
```
```tsx
// components/BanTable.tsx
import type { Ban } from "../types/ban";
```
---
## 3. Type Safety in API Calls
- Every API call must have a **typed request** and **typed response**.
- Define response shapes as TypeScript interfaces in `types/` and cast the response through them.
- Use a **central API client** (e.g., a thin wrapper around `fetch` or `axios`) that returns typed data — individual components never call `fetch` directly.
- Validate or assert the response structure at the boundary when dealing with untrusted data; for critical flows, consider a runtime validation library (e.g., `zod`).
- API endpoint paths are **constants** defined in a single file (`api/endpoints.ts`) — never hard-code URLs in components.
```ts
// api/client.ts
const BASE_URL = import.meta.env.VITE_API_URL ?? "/api";
async function get<T>(path: string): Promise<T> {
const response: Response = await fetch(`${BASE_URL}${path}`, {
credentials: "include",
});
if (!response.ok) {
throw new ApiError(response.status, await response.text());
}
return (await response.json()) as T;
}
export const api = { get, post, put, del } as const;
```
```ts
// api/bans.ts
import type { BanListResponse } from "../types/ban";
import { api } from "./client";
export async function fetchBans(hours: number): Promise<BanListResponse> {
return api.get<BanListResponse>(`/bans?hours=${hours}`);
}
```
---
## 4. Code Organization
### Project Structure
```
frontend/
├── public/
├── src/
│ ├── api/ # API client, endpoint definitions, per-domain request files
│ ├── assets/ # Static images, fonts, icons
│ ├── components/ # Reusable UI components (buttons, modals, tables, etc.)
│ ├── hooks/ # Custom React hooks
│ ├── layouts/ # Page-level layout wrappers (sidebar, header, etc.)
│ ├── pages/ # Route-level page components (one per route)
│ ├── providers/ # React context providers (auth, theme, etc.)
│ ├── theme/ # Fluent UI custom theme, tokens, and overrides
│ ├── types/ # Shared TypeScript type definitions
│ ├── utils/ # Pure helper functions, constants, formatters
│ ├── App.tsx # Root component, FluentProvider + router setup
│ ├── main.tsx # Entry point
│ └── vite-env.d.ts # Vite type shims
├── .eslintrc.cjs
├── .prettierrc
├── tsconfig.json
├── vite.config.ts
└── package.json
```
### Separation of Concerns
- **Pages** handle routing and compose layout + components — they contain no business logic.
- **Components** are reusable, receive data via props, and emit changes via callbacks — they never call the API directly.
- **Hooks** encapsulate stateful logic, side effects, and API calls so components stay declarative.
- **API layer** handles all HTTP communication — components and hooks consume typed functions from `api/`, never raw `fetch`.
- **Types** are purely declarative — no runtime code in `types/` files.
- **Utils** are pure functions with no side effects and no React dependency.
- **Theme** contains exclusively Fluent UI custom token overrides and theme definitions — no component logic.
---
## 5. UI Framework — Fluent UI React (v9)
- **Fluent UI React Components v9** (`@fluentui/react-components`) is the only UI component library allowed — do not add alternative component libraries (Material UI, Chakra, Ant Design, etc.).
- Install via npm:
```bash
npm install @fluentui/react-components @fluentui/react-icons
```
### FluentProvider
- Wrap the entire application in `<FluentProvider>` at the root — this supplies the theme and design tokens to all Fluent components.
- The provider must sit above the router so every page inherits the theme.
```tsx
// App.tsx
import { FluentProvider, webLightTheme } from "@fluentui/react-components";
import { BrowserRouter } from "react-router-dom";
import AppRoutes from "./AppRoutes";
function App(): JSX.Element {
return (
<FluentProvider theme={webLightTheme}>
<BrowserRouter>
<AppRoutes />
</BrowserRouter>
</FluentProvider>
);
}
export default App;
```
### Theming & Design Tokens
- Use the built-in themes (`webLightTheme`, `webDarkTheme`) as the base.
- Customise design tokens by creating a **custom theme** in `theme/` — never override Fluent styles with raw CSS.
- Reference tokens via the `tokens` object from `@fluentui/react-components` when writing `makeStyles` rules.
- If light/dark mode is needed, switch the `theme` prop on `FluentProvider` — never duplicate style definitions for each mode.
```ts
// theme/customTheme.ts
import { createLightTheme, createDarkTheme } from "@fluentui/react-components";
import type { BrandVariants, Theme } from "@fluentui/react-components";
const brandColors: BrandVariants = {
10: "#020305",
// ... define brand colour ramp
160: "#e8ebf9",
};
export const lightTheme: Theme = createLightTheme(brandColors);
export const darkTheme: Theme = createDarkTheme(brandColors);
```
### Styling with `makeStyles` (Griffel)
- All custom styling is done via `makeStyles` from `@fluentui/react-components` — Fluent UI uses **Griffel** (CSS-in-JS with atomic classes) under the hood.
- Never use inline `style` props, global CSS, or external CSS frameworks for Fluent components.
- Co-locate styles in the same file as the component they belong to, defined above the component function.
- Use `mergeClasses` when combining multiple style sets conditionally.
- Reference Fluent **design tokens** (`tokens.colorBrandBackground`, `tokens.fontSizeBase300`, etc.) instead of hard-coded values — this ensures consistency and automatic theme support.
```tsx
import { makeStyles, tokens, mergeClasses } from "@fluentui/react-components";
const useStyles = makeStyles({
root: {
padding: tokens.spacingVerticalM,
backgroundColor: tokens.colorNeutralBackground1,
},
highlighted: {
backgroundColor: tokens.colorPaletteRedBackground2,
},
});
function BanCard({ isHighlighted }: BanCardProps): JSX.Element {
const styles = useStyles();
return (
<div className={mergeClasses(styles.root, isHighlighted && styles.highlighted)}>
{/* ... */}
</div>
);
}
```
### Component Usage Rules
- **Always** prefer Fluent UI components over plain HTML elements for interactive and presentational UI: `<Button>`, `<Input>`, `<Table>`, `<Dialog>`, `<Card>`, `<Badge>`, `<Spinner>`, `<Toast>`, `<MessageBar>`, etc.
- Use `<DataGrid>` for data-heavy tables (ban lists, jail lists) — it provides sorting, selection, and accessibility out of the box.
- Use Fluent UI `<Dialog>` for modals and confirmations — never build custom modal overlays.
- Use `@fluentui/react-icons` for all icons — do not mix icon libraries.
- Customise Fluent components only through their public API (props, slots, `makeStyles`) — never patch internal DOM or override internal class names.
### Libraries you must NOT use alongside Fluent UI
- `tailwindcss` — use `makeStyles` and design tokens.
- `styled-components` / `emotion` — Fluent UI uses Griffel; mixing CSS-in-JS runtimes causes conflicts.
- `@mui/*`, `antd`, `chakra-ui` — one design system only.
- Global CSS files that target Fluent class names — use `makeStyles` overrides.
---
## 6. Component Rules
- One component per file. The filename matches the component name: `BanTable.tsx` exports `BanTable`.
- Use **function declarations** for components — not arrow-function variables.
- Keep components **small and focused** — if a component exceeds ~150 lines, split it.
- Props are defined as an `interface` named `<ComponentName>Props` in the same file (or imported from `types/` if shared).
- Destructure props in the function signature.
- Never mutate props or state directly — always use immutable update patterns.
- Avoid inline styles — use `makeStyles` from Fluent UI for all custom styling (see section 5).
- Supply a `key` prop whenever rendering lists — never use array indices as keys if the list can reorder.
- Prefer Fluent UI components (`Button`, `Table`, `Input`, …) over raw HTML elements for any interactive or styled element.
```tsx
import { Table, TableBody, TableRow, TableCell, Button } from "@fluentui/react-components";
import type { Ban } from "../types/ban";
interface BanTableProps {
bans: Ban[];
onUnban: (ip: string) => void;
}
function BanTable({ bans, onUnban }: BanTableProps): JSX.Element {
return (
<Table>
<TableBody>
{bans.map((ban) => (
<TableRow key={ban.ip}>
<TableCell>{ban.ip}</TableCell>
<TableCell>{ban.jail}</TableCell>
<TableCell>
<Button appearance="subtle" onClick={() => onUnban(ban.ip)}>Unban</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
);
}
export default BanTable;
```
---
## 7. Hooks & State Management
- Prefix custom hooks with `use` — e.g., `useBans`, `useAuth`, `useJails`.
- Each hook lives in its own file under `hooks/`.
- Use `useState` for local UI state, `useReducer` for complex state transitions.
- Use **React Context** sparingly — only for truly global concerns (auth, theme). Do not use context as a replacement for prop drilling one or two levels.
- Avoid `useEffect` for derived data — compute it during render or use `useMemo`.
- Always include the correct dependency arrays in `useEffect`, `useMemo`, and `useCallback`. Disable the ESLint exhaustive-deps rule **only** with a comment explaining why.
- Clean up side effects (subscriptions, timers, abort controllers) in the `useEffect` cleanup function.
```tsx
// hooks/useBans.ts
import { useState, useEffect } from "react";
import type { Ban } from "../types/ban";
import { fetchBans } from "../api/bans";
interface UseBansResult {
bans: Ban[];
loading: boolean;
error: string | null;
}
function useBans(hours: number): UseBansResult {
const [bans, setBans] = useState<Ban[]>([]);
const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const controller = new AbortController();
async function load(): Promise<void> {
setLoading(true);
try {
const data = await fetchBans(hours);
setBans(data.bans);
setError(null);
} catch (err) {
if (!controller.signal.aborted) {
setError(err instanceof Error ? err.message : "Unknown error");
}
} finally {
setLoading(false);
}
}
load();
return () => controller.abort();
}, [hours]);
return { bans, loading, error };
}
export default useBans;
```
---
## 8. Naming Conventions
| Element | Convention | Example |
|---|---|---|
| Components | PascalCase | `BanTable`, `JailCard` |
| Component files | PascalCase `.tsx` | `BanTable.tsx` |
| Hooks | camelCase with `use` prefix | `useBans`, `useAuth` |
| Hook files | camelCase `.ts` | `useBans.ts` |
| Type / Interface | PascalCase | `BanEntry`, `JailListResponse` |
| Type files | camelCase `.ts` | `ban.ts`, `jail.ts` |
| Utility functions | camelCase | `formatDate`, `buildQuery` |
| Constants | UPPER_SNAKE_CASE | `MAX_RETRIES`, `API_BASE_URL` |
| makeStyles hooks | `useStyles` (file-scoped) | `const useStyles = makeStyles({…})` |
| makeStyles keys | camelCase slot names | `root`, `header`, `highlighted` |
| Directories | lowercase kebabcase or camelCase | `components/`, `hooks/` |
| Boolean props/variables | `is`/`has`/`should` prefix | `isLoading`, `hasError` |
---
## 9. Linting & Formatting
- **ESLint** with the following plugins is required:
- `@typescript-eslint/eslint-plugin` — TypeScript-specific rules.
- `eslint-plugin-react` — React best practices.
- `eslint-plugin-react-hooks` — enforce rules of hooks.
- `eslint-plugin-import` — ordered and valid imports.
- **Prettier** handles all formatting — ESLint must not conflict with Prettier (use `eslint-config-prettier`).
- Format on save is expected — every developer must enable it in their editor.
- Run `eslint . --max-warnings 0` and `prettier --check .` in CI — zero warnings, zero formatting diffs.
- Line length: **100 characters** max.
- Strings: use **double quotes** (`"`).
- Semicolons: **always**.
- Trailing commas: **all** (ES5+).
- Indentation: **2 spaces**.
- No unused variables, no unused imports, no `@ts-ignore` without an accompanying comment.
- Import order (enforced by ESLint): React → third-party → aliases → relative, each group separated by a blank line.
```jsonc
// .prettierrc
{
"semi": true,
"singleQuote": false,
"trailingComma": "all",
"printWidth": 100,
"tabWidth": 2
}
```
---
## 10. Clean Code Principles
- **Single Responsibility:** Every function, hook, and component does one thing well.
- **DRY (Don't Repeat Yourself):** Extract repeated JSX into components, repeated logic into hooks or utils. If you copy-paste, refactor.
- **KISS (Keep It Simple, Stupid):** Prefer the simplest solution that works. Avoid premature abstraction.
- **Meaningful Names:** Variable and function names describe **what**, not **how**. Avoid abbreviations (`btn``button`, `idx``index`) except universally understood ones (`id`, `url`, `ip`).
- **Small Functions:** If a function exceeds ~30 lines, it likely does too much — split it.
- **No Magic Numbers / Strings:** Extract constants with descriptive names.
- **Explicit over Implicit:** Favor clarity over cleverness. Code is written once and read many times.
- **No Dead Code:** Remove unused functions, commented-out blocks, and unreachable branches before committing.
- **Early Returns:** Reduce nesting by returning early from guard clauses.
- **Immutability:** Default to `const`. Use spread / `map` / `filter` instead of mutating arrays and objects.
```tsx
// Bad — magic number, unclear name
if (data.length > 50) { ... }
// Good
const MAX_VISIBLE_BANS = 50;
if (data.length > MAX_VISIBLE_BANS) { ... }
```
---
## 11. Error Handling
- Wrap API calls in `try-catch` inside hooks — components should never see raw exceptions.
- Display user-friendly error messages — never expose stack traces or raw server responses in the UI.
- Use an **error boundary** (`ErrorBoundary` component) at the page level to catch unexpected render errors.
- Log errors to the console (or a future logging service) with sufficient context for debugging.
- Always handle the **loading**, **error**, and **empty** states for every data-driven component.
---
## 12. Performance
- Use `React.memo` only when profiling reveals unnecessary re-renders — do not wrap every component by default.
- Use `useMemo` and `useCallback` for expensive computations and stable callback references passed to child components — not for trivial values.
- Lazy-load route-level pages with `React.lazy` + `Suspense` to reduce initial bundle size.
- Avoid creating new objects or arrays inside render unless necessary — stable references prevent child re-renders.
- Keep bundle size in check — review dependencies before adding them and prefer lightweight alternatives.
---
## 13. Accessibility
- Use semantic HTML elements (`<button>`, `<nav>`, `<table>`, `<main>`, `<header>`) — not `<div>` with click handlers.
- Every interactive element must be **keyboard accessible** (focusable, operable with Enter/Space/Escape as appropriate).
- Images and icons require `alt` text or `aria-label`.
- Form inputs must have associated `<label>` elements.
- Maintain sufficient color contrast ratios (WCAG AA minimum).
- Test with a screen reader periodically.
---
## 14. Testing
- Write tests for every new component, hook, and utility function.
- Use **Vitest** (or Jest) as the test runner and **React Testing Library** for component tests.
- Test **behavior**, not implementation — query by role, label, or text, never by CSS class or internal state.
- Mock API calls at the network layer (e.g., `msw` — Mock Service Worker) — components should not know about mocks.
- Aim for **>80 % line coverage** — critical paths (auth flow, ban/unban actions) must be 100 %.
- Test name pattern: `it("should <expected behavior> when <condition>")`.
- Wrap components under test in `<FluentProvider>` so Fluent UI styles and tokens resolve correctly:
```tsx
import { render, screen } from "@testing-library/react";
import { FluentProvider, webLightTheme } from "@fluentui/react-components";
import BanTable from "./BanTable";
import type { Ban } from "../types/ban";
const mockBans: Ban[] = [
{ ip: "192.168.1.1", jail: "sshd", bannedAt: "2026-02-28T12:00:00Z", expiresAt: null, banCount: 3, country: "DE" },
];
function renderWithProvider(ui: JSX.Element) {
return render(<FluentProvider theme={webLightTheme}>{ui}</FluentProvider>);
}
it("should render a row for each ban", () => {
renderWithProvider(<BanTable bans={mockBans} onUnban={vi.fn()} />);
expect(screen.getByText("192.168.1.1")).toBeInTheDocument();
});
```
---
## 15. Git & Workflow
- **Branch naming:** `feature/<short-description>`, `fix/<short-description>`, `chore/<short-description>`.
- **Commit messages:** imperative tense, max 72 chars first line (`Add ban table component`, `Fix date formatting in dashboard`).
- Every merge request must pass: ESLint, Prettier, TypeScript compiler, all tests.
- Do not merge with failing CI.
- Keep pull requests small and focused — one feature or fix per PR.
- Review your own diff before requesting review.
---
## 16. Quick Reference — Do / Don't
| Do | Don't |
|---|---|
| Type every prop, state, and return value | Use `any` or leave types implicit |
| Keep shared types in `types/` | Duplicate interfaces across files |
| Call API from hooks, not components | Scatter `fetch` calls across the codebase |
| Use `import type` for type-only imports | Import types as regular imports |
| One component per file | Export multiple components from one file |
| Destructure props in the signature | Access `props.x` throughout the body |
| Use Fluent UI components for all interactive UI | Build custom buttons, inputs, dialogs from scratch |
| Style with `makeStyles` + design tokens | Use inline styles, global CSS, or Tailwind |
| Wrap the app in `<FluentProvider>` | Render Fluent components outside a provider |
| Use `@fluentui/react-icons` for icons | Mix multiple icon libraries |
| Use semantic HTML elements | Use `<div>` for everything |
| Handle loading, error, and empty states | Only handle the happy path |
| Name booleans with `is`/`has`/`should` | Name booleans as plain nouns (`loading`) |
| Extract constants for magic values | Hard-code numbers and strings |
| Clean up effects (abort, unsub) | Let effects leak resources |
| Format and lint before every commit | Push code that doesn't pass CI |

View File

@@ -0,0 +1,12 @@
[codespell]
# THANKS - names
skip = .git,*.pdf,*.svg,venv,.codespellrc,.typos.toml,THANKS,*test*.log,logs
check-hidden = true
# Ignore all acronyms etc as plenty e.g. in fail2ban/server/strptime.py
# Try to identify incomplete words which are part of a regex, hence having [] at the beginning
# Ignore all urls as something with :// in it
# Ignore all lines with codespell-ignore in them for pragma annotation
ignore-regex = (\b([A-Z][A-Z][A-Z]+|gir\.st)\b)|\[[a-zA-Z]+\][a-z]+\b|[a-z]+://\S+|.*codespell-ignore.*
# some oddly named variables, some names, etc
# wee -- comes in regex etc for weeks
ignore-words-list = assertIn,theis,timere,alls,wee,wight,ans,re-use,pre-emptive

View File

@@ -0,0 +1,12 @@
[run]
branch = True
source =
config
fail2ban
[report]
exclude_lines =
pragma: ?no ?cover
pragma: ?${F2B_PY}.x no ?cover
pragma: ?systemd no ?cover

1
fail2ban-master/.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
ChangeLog linguist-language=Markdown

5
fail2ban-master/.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,5 @@
# These are supported funding model platforms
github: [sebres]
custom: [https://paypal.me/sebres]
liberapay: sebres

View File

@@ -0,0 +1,70 @@
---
name: Bug report
about: Report a bug within the fail2ban engines (not filters or jails)
title: '[BR]: '
labels: bug
assignees: ''
---
<!--
- Before reporting, please make sure to search the open and closed issues for any reports in the past.
- Use this issue template to report a bug in the fail2ban engine (not in a filter or jail).
- If you want to request a feature or a new filter, please use "Feature request" or "Filter request" instead.
- If you have rather some question, please open or join to some discussion.
We will be very grateful, if your problem was described as completely as possible,
enclosing excerpts from logs (if possible within DEBUG mode, if no errors evident
within INFO mode), and configuration in particular of effected relevant settings
(e.g., with ` fail2ban-client -d | grep 'affected-jail-name' ` for a particular
jail troubleshooting).
Thank you in advance for the details, because such issues like "It does not work"
alone could not help to resolve anything!
Thanks!
(you can remove this paragraph and other comments upon reading)
-->
### Environment:
<!--
Fill out and check (`[x]`) the boxes which apply. If your Fail2Ban version is outdated,
and you can't verify that the issue persists in the recent release, better seek support
from the distribution you obtained Fail2Ban from
-->
- Fail2Ban version <!-- including any possible distribution suffixes --> :
- OS, including release name/version :
- [ ] Fail2Ban installed via OS/distribution mechanisms
- [ ] You have not applied any additional foreign patches to the codebase
- [ ] Some customizations were done to the configuration (provide details below is so)
### The issue:
<!-- summary here -->
#### Steps to reproduce
#### Expected behavior
#### Observed behavior
#### Any additional information
### Configuration, dump and another helpful excerpts
#### Any customizations done to /etc/fail2ban/ configuration
<!-- put your configuration excerpts between next 2 lines -->
```
```
#### Relevant parts of /var/log/fail2ban.log file:
<!-- preferably obtained while running fail2ban with `loglevel = 4` -->
<!-- put your log excerpt between next 2 lines -->
```
```
#### Relevant lines from monitored log files:
<!-- put your log excerpt between next 2 lines -->
```
```

View File

@@ -0,0 +1,35 @@
---
name: Feature request
about: Suggest an idea or an enhancement for this project
title: '[RFE]: '
labels: enhancement
assignees: ''
---
<!--
- Before requesting, please make sure to search the open and closed issues for any requests in the past.
- Use this issue template to request a feature in the fail2ban engine (not a new filter or jail).
- If you want to request a new filter or failregex, please use "Filter request" instead.
- If you have rather some question, please open or join to some discussion.
-->
#### Feature request type
<!--
Please provide a summary description of the feature request.
-->
#### Description
<!--
Please describe the feature in more detail.
-->
#### Considered alternatives
<!--
A clear and concise description of any alternative solutions or features you've considered.
-->
#### Any additional information
<!--
Add any other context or screenshots about the feature request here.
-->

View File

@@ -0,0 +1,59 @@
---
name: Filter request
about: Request a new jail or filter to be supported or existing filter extended with new failregex
title: '[FR]: '
labels: filter-request
assignees: ''
---
<!--
- Before requesting, please make sure to search the open and closed issues for any requests in the past.
- Sometimes failregex have been already requested before but are not implemented yet due to various reasons.
- If there are no hits for your concerns, please proceed otherwise add a comment to the related issue (also if it is closed).
- If you want to request a new feature, please use "Feature request" instead.
- If you have rather some question, please open or join to some discussion.
-->
### Environment:
<!--
Fill out and check (`[x]`) the boxes which apply.
-->
- Fail2Ban version <!-- including any possible distribution suffixes --> :
- OS, including release name/version :
#### Service, project or product which log or journal should be monitored
- Name of filter or jail in Fail2Ban (if already exists) :
- Service, project or product name, including release name/version :
- Repository or URL (if known) :
- Service type :
- Ports and protocols the service is listening :
#### Log or journal information
<!-- Delete unrelated group -->
<!-- Log file -->
- Log file name(s) :
<!-- Systemd journal -->
- Journal identifier or unit name :
#### Any additional information
### Relevant lines from monitored log files:
#### failures in sense of fail2ban filter (fail2ban must match):
<!-- put your log excerpt between next 2 lines -->
```
```
#### legitimate messages (fail2ban should not consider as failures):
<!-- put your log excerpt between next 2 lines -->
```
```

View File

@@ -0,0 +1,10 @@
Before submitting your PR, please review the following checklist:
- [ ] **CONSIDER adding a unit test** if your PR resolves an issue
- [ ] **LIST ISSUES** this PR resolves or describe the approach in detail
- [ ] **MAKE SURE** this PR doesn't break existing tests
- [ ] **KEEP PR small** so it could be easily reviewed
- [ ] **AVOID** making unnecessary stylistic changes in unrelated code
- [ ] **ACCOMPANY** each new `failregex` for filter `X` with sample log lines
(and `# failJSON`) within `fail2ban/tests/files/logs/X` file
- [ ] **PROVIDE ChangeLog** entry describing the pull request

View File

@@ -0,0 +1,22 @@
---
name: Codespell
on:
push:
branches: [master]
pull_request:
branches: [master]
permissions:
contents: read
jobs:
codespell:
name: Check for spelling errors
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Codespell
uses: codespell-project/actions-codespell@v2

View File

@@ -0,0 +1,102 @@
name: CI
# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
push:
paths-ignore:
- 'doc/**'
- 'files/**'
- 'man/**'
pull_request:
paths-ignore:
- 'doc/**'
- 'files/**'
- 'man/**'
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.8, 3.9, '3.10', '3.11', '3.12', '3.13', '3.14', '3.15.0-alpha.5', pypy3.11]
fail-fast: false
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Grant systemd-journal access
run: sudo usermod -a -G systemd-journal "$USER" || echo 'no systemd-journal access'
- name: Python version
run: |
F2B_PY=$(python -c "import sys; print(sys.version)")
echo "Python: ${{ matrix.python-version }} -- ${F2B_PY/$'\n'/ }"
F2B_PYV=$(echo "${F2B_PY}" | grep -oP '^\d+(?:\.\d+)')
F2B_PY=${F2B_PY:0:1}
echo "Set F2B_PY=$F2B_PY, F2B_PYV=$F2B_PYV"
echo "F2B_PY=$F2B_PY" >> $GITHUB_ENV
echo "F2B_PYV=$F2B_PYV" >> $GITHUB_ENV
# for GHA we need to monitor all journals, since it cannot be found using SYSTEM_ONLY(4):
echo "F2B_SYSTEMD_DEFAULT_FLAGS=0" >> $GITHUB_ENV
- name: Install dependencies
run: |
#if [[ "$F2B_PY" = 3 ]]; then python -m pip install --upgrade pip || echo "can't upgrade pip"; fi
#sudo apt-get -y install python${F2B_PY/2/}-pyinotify || echo 'inotify not available'
python -m pip install pyinotify || echo 'inotify not available'
sudo apt-get -y install sqlite3 || echo 'sqlite3 not available'
#sudo apt-get -y install python${F2B_PY/2/}-systemd || echo 'systemd not available'
sudo apt-get -y install libsystemd-dev || echo 'systemd dependencies seems to be unavailable'
python -m pip install systemd-python || echo 'systemd not available'
# readline if available as module:
python -c 'import readline' 2> /dev/null || python -m pip install readline || echo 'readline not available'
# asyncore/asynchat:
if dpkg --compare-versions "$F2B_PYV" ge 3.12; then
#sudo apt-get -y install python${F2B_PY/2/}-setuptools || echo 'setuptools not unavailable'
python -m pip install setuptools || echo "can't install setuptools"
# don't install async* modules, we need to cover bundled-in libraries:
#python -m pip install pyasynchat || echo "can't install pyasynchat";
#python -m pip install pyasyncore || echo "can't install pyasyncore";
fi
# aiosmtpd in test_smtp (for 3.10+, no need to test it everywhere):
if dpkg --compare-versions "$F2B_PYV" ge 3.10; then
#sudo apt-get -y install python${F2B_PY/2/}-aiosmtpd || echo 'aiosmtpd not available'
python -m pip install aiosmtpd || echo 'aiosmtpd not available'
fi
- name: Before scripts
run: |
cd "$GITHUB_WORKSPACE"
_debug() { echo -n "$1 "; err=$("${@:2}" 2>&1) && echo 'OK' || echo -e "FAIL\n$err"; }
# (debug) output current preferred encoding:
echo 'Encodings:' $(python -c 'import locale, sys; from fail2ban.helpers import PREFER_ENC; print(PREFER_ENC, locale.getpreferredencoding(), (sys.stdout and sys.stdout.encoding))')
# (debug) backend availabilities:
echo 'Backends:'
_debug '- systemd:' python -c 'from fail2ban.server.filtersystemd import FilterSystemd'
#_debug '- systemd (root): ' sudo python -c 'from fail2ban.server.filtersystemd import FilterSystemd'
_debug '- pyinotify:' python -c 'from fail2ban.server.filterpyinotify import FilterPyinotify'
- name: Test suite
run: |
#python setup.py test
python bin/fail2ban-testcases --verbosity=2
#- name: Test suite (debug some systemd tests only)
#run: python bin/fail2ban-testcases --verbosity=2 "[sS]ystemd|[jJ]ournal"
#run: python bin/fail2ban-testcases --verbosity=2 -l 5 "test_WrongChar"
- name: Build
run: python setup.py build
#- name: Test initd scripts
# run: shellcheck -s bash -e SC1090,SC1091 files/debian-initd

View File

@@ -0,0 +1,32 @@
name: Upload Package to PyPI
on:
workflow_dispatch:
release:
types: [created]
jobs:
pypi-publish:
name: Publish release to PyPI
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/fail2ban
permissions:
id-token: write
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.x"
- name: Install dependencies
run: |
python -m pip install --upgrade pip || echo "can't upgrade pip"
pip install setuptools wheel || echo "can't install/update setuptools or wheel"
- name: Build package
run: |
# python -m build ...
python setup.py sdist bdist_wheel
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1

13
fail2ban-master/.gitignore vendored Normal file
View File

@@ -0,0 +1,13 @@
*~
build
dist
*.pyc
htmlcov
.coverage
*.orig
*.rej
*.bak
__pycache__
.vagrant/
.idea/
.venv/

5
fail2ban-master/.mailmap Normal file
View File

@@ -0,0 +1,5 @@
Lee Clemens <java@leeclemens.net>
Serg G. Brester <info@sebres.de>
Serg G. Brester <serg.brester@sebres.de>
Serg G. Brester <sergey.brester@W7-DEHBG0189.wincor-nixdorf.com>
Viktor Szépe <viktor@szepe.net>

37
fail2ban-master/.pylintrc Normal file
View File

@@ -0,0 +1,37 @@
# Custom pylint configuration for the Fail2Ban project
#
# Set your PYLINTRC environment variable to point to this file
# e.g.
# export PYLINTRC=$PWD/.pylintrc
[FORMAT]
indent-string='\t'
[BASIC]
# Fail2Ban uses non-conventional to Python world camel-casing
# These regexps were originally borrowed from 0.4.x series of
# PyMVPA which had similar conventions.
# Regular expression which should only match correct module names
module-rgx=(([a-z][a-z0-9_]*)|([A-Z][a-zA-Z0-9_]+))$
attr-rgx=[a-z_][a-zA-Z0-9_]{2,30}
# Regular expression which should only match correct class names
class-rgx=[A-Z_]+[a-zA-Z0-9]+$
# Regular expression which should only match correct function names
function-rgx=[a-z_]+[a-z_][a-zA-Z0-9]*$
# Regular expression which should only match correct method names
method-rgx=([a-z_]|__)[a-zA-Z0-9]*(__)?$
# Regular expression which should only match correct argument names
argument-rgx=[a-z][a-zA-Z0-9]*_*[a-zA-Z0-9]*_*[a-zA-Z0-9]*_?$
# Regular expression which should only match correct variable names
variable-rgx=([a-z_]+[a-zA-Z0-9]*_*[a-zA-Z0-9]*_*[a-zA-Z0-9]*_?||(__.*__))$||[A-Z]
# Regular expression which should only match correct module level names
# Default: (([A-Z_][A-Z1-9_]*)|(__.*__))$
const-rgx=([a-z_]+[a-zA-Z0-9]*_*[a-zA-Z0-9]*_*[a-zA-Z0-9]*_?|__.*__)$||[A-Z]

View File

@@ -0,0 +1,35 @@
[files]
extend-exclude = [
".git/",
".codespellrc",
"fail2ban/tests/files/logs/",
]
ignore-hidden = false
[default]
extend-ignore-re = [
"Christoph Theis",
"\\[[0-9a-f]{7,8}\\]",
"hash_[0-9a-f]{38}",
"\t[0-9.-]+[ A-Z]+",
"Erreur d'authentification",
"WebEMailExtrac",
"ssh2: RSA 14:ba:xx",
"\\[Cc\\]lient",
"\\[Gg\\]ot",
"\\[nN\\]ot",
"\\[Uu\\]nknown",
"\\[uU\\]ser",
"\\[Uu\\]\\(\\?:ser",
]
[default.extend-words]
"alls" = "alls"
"helo" = "helo"
[default.extend-identifiers]
"failManager2nd" = "failManager2nd"
"log2nd" = "log2nd"
"routeros" = "routeros"
"REFERERS" = "REFERERS"
"tre_search" = "tre_search"

View File

@@ -0,0 +1,27 @@
Guidelines on Fail2Ban contributions
====================================
### You found a severe security vulnerability in Fail2Ban?
email details to fail2ban-vulnerabilities at lists dot sourceforge dot net .
### You need some new features, you found bugs?
visit [Issues](https://github.com/fail2ban/fail2ban/issues)
and if your issue is not yet known -- file a bug report. See
[Fail2Ban wiki](http://www.fail2ban.org/wiki/index.php/HOWTO_Seek_Help)
on further instructions.
### You would like to troubleshoot or discuss?
join the [mailing list](https://lists.sourceforge.net/lists/listinfo/fail2ban-users)
### You would like to contribute (new filters/actions/code/documentation)?
send a [pull request](https://github.com/fail2ban/fail2ban/pulls)
Pull requests guidelines
========================
- If there is an issue on github to be closed by the pull request, include
```Closes #ISSUE``` (where ISSUE is issue's number)
- Add a brief summary of the change to the ChangeLog file into a corresponding
section out of Fixes, New Features or Enhancements (improvements to existing
features)

368
fail2ban-master/COPYING Normal file
View File

@@ -0,0 +1,368 @@
The following copyright applies to all files present in the Fail2ban package,
except if a different copyright is explicitly defined in this file.
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
---------------------------------
The file server/iso8601.py is licensed under the following terms.
Copyright (c) 2007 Michael Twomey
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

2752
fail2ban-master/ChangeLog Normal file

File diff suppressed because it is too large Load Diff

299
fail2ban-master/DEVELOP Normal file
View File

@@ -0,0 +1,299 @@
.. __ _ _ ___ _
/ _|__ _(_) |_ ) |__ __ _ _ _
| _/ _` | | |/ /| '_ \/ _` | ' \
|_| \__,_|_|_/___|_.__/\__,_|_||_|
================================================================================
How to develop for Fail2Ban
================================================================================
Fail2Ban uses GIT (http://git-scm.com/) distributed source control. This gives
each developer their own complete copy of the entire repository. Developers can
add and switch branches and commit changes when ever they want and then ask a
maintainer to merge their changes.
Fail2Ban uses GitHub (https://github.com/fail2ban/fail2ban) to manage access to
the Git repository. GitHub provides free hosting for open-source projects as
well as a web-based Git repository browser and an issue tracker.
If you are familiar with Python and you have a bug fix or a feature that you
would like to add to Fail2Ban, the best way to do so it to use the GitHub Pull
Request feature. You can find more details on the Fail2Ban wiki
(http://www.fail2ban.org/wiki/index.php/Get_Involved)
Pull Requests
=============
When submitting pull requests on GitHub we ask you to:
* Clearly describe the problem you're solving;
* Don't introduce regressions that will make it hard for systems administrators
to update;
* If adding a major feature rebase your changes on master and get to a single commit;
* Include test cases (see below);
* Include sample logs (if relevant);
* Include a change to the relevant section of the ChangeLog; and
* Include yourself in THANKS if not already there.
If you are developing filters see the FILTERS file for documentation.
Code Testing
============
Existing tests can be run by executing `bin/fail2ban-testcases`. It has
options like --log-level that will probably be useful. Run
`bin/fail2ban-testcases --help` for the full list of options.
Test cases should cover all usual cases, all exception cases and all inside
/ outside boundary conditions.
Test cases should cover all branches. The coverage tool will help identify
missing branches. Also see http://nedbatchelder.com/code/coverage/branch.html
for more details.
Install the package python-coverage to visualise your test coverage. Run the
following (note: on Debian-based systems, the script is called
`python-coverage`)::
coverage run bin/fail2ban-testcases
coverage report
Optionally:
coverage html
And then browse htmlcov/index.html and see how much coverage your test cases
exert over the code base. Full coverage is a good thing however it may not be
complete. Try to ensure tests cover as many independent paths through the
code.
Manual Execution. To run in a development environment do::
./fail2ban-client -c config/ -s /tmp/f2b.sock -i start
some quick commands::
status
add test pyinotify
status test
set test addaction iptables
set test actionban iptables echo <ip> <cidr> >> /tmp/ban
set test actionunban iptables echo <ip> <cidr> >> /tmp/unban
get test actionban iptables
get test actionunban iptables
set test banip 192.168.2.2
status test
Testing with vagrant
--------------------
Testing can now be done inside a vagrant VM. Vagrantfile provided in
source code repository established two VMs:
- VM "secure" which can be used for testing fail2ban code.
- VM "attacker" which can be used to perform attack against our "secure" VM.
Both VMs are sharing the 192.168.200/24 network. If you are using this network
take a look into the Vagrantfile and change the IP.
Coding Standards
================
Style
-----
Please use tabs for now. Keep to 80 columns, at least for readable text.
Tests
-----
Add tests. They should test all the code you add in a meaning way.
Coverage
--------
Test coverage should always increase as you add code.
You may use "# pragma: no cover" in the code for branches of code that support
older versions on python. For all other uses of "pragma: no cover" or
"pragma: no branch" document the reason why its not covered. "I haven't written
a test case" isn't a sufficient reason.
pyflakes
--------
pyflakes can be used to find unused imports, and unused, undefined and
redefined variables. pyflakes should be run in any python code, including
python based actions::
pyflakes bin/ config/ fail2ban/
Documentation
-------------
Ensure this documentation is up to date after changes. Also ensure that the man
pages still are accurate. Ensure that there is sufficient documentation for
your new features to be used.
Bugs
----
Remove them and don't add any more.
Git
---
Use the following tags in your commit messages:
* 'BF:' for bug fixes
* 'DOC:' for documentation fixes
* 'ENH:' for enhancements
* 'TST:' for commits concerning tests only (thus not touching the main code-base)
Multiple tags could be joined with +, e.g. "BF+TST:".
Use the text "closes #333"/"resolves #333 "/"fixes #333" where 333 represents
an issue that is closed. Other text and details in link below.
See: https://help.github.com/articles/closing-issues-via-commit-messages
If merge resulted in conflicts, clarify what changes were done to
corresponding files in the 'Conflicts:' section of the merge commit
message. See e.g. https://github.com/fail2ban/fail2ban/commit/f5a8a8ac
Adding Actions
--------------
If you add an action.d/*.conf file also add a example in config/jail.conf
with enabled=false and maxretry=5 for ssh.
Design
======
Fail2Ban was initially developed with Python 2.3 (IIRC). It should
still be compatible with Python 2.4 and such compatibility assurance
makes code ... old-fashioned in many places (RF-Note). In 0.7 the
design went through major re-factoring into client/server,
a-thread-per-jail design which made it a bit difficult to follow.
Below you can find a sketchy description of the main components of the
system to orient yourself better.
server/
------
Core classes hierarchy (feel welcome to draw a better/more complete
one)::
-> inheritance
+ delegation
* storage of multiple instances
RF-Note just a note which might be useful to address while doing RF
JailThread -> Filter -> FileFilter -> {FilterPoll, FilterPyinotify, ...}
| * FileContainer
+ FailManager
+ DateDetector
+ Jail (provided in __init__) which contains this Filter
(used for passing tickets from FailManager to Jail's __queue)
Server
+ Jails
* Jail
+ Filter (in __filter)
* tickets (in __queue)
+ Actions (in __action)
* Action
+ BanManager
failmanager.py
~~~~~~~~~~~~~~
FailManager
Keeps track of failures, recorded as 'tickets'. All operations are
done via acquiring a lock
FailManagerEmpty(Exception)
raised by FailManager.toBan after reaching the list of tickets
(RF-Note: asks to become a generator ;) )
filter.py
~~~~~~~~~~
Filter(JailThread)
Wraps (non-threaded) FailManager (and proxies to it quite a bit),
and provides all primary logic for processing new lines, what IPs to
ignore, etc
.failManager [FailManager]
.dateDetector [DateDetector]
.__failRegex [list]
.__ignoreRegex [list]
Contains regular expressions for failures and ignores
.__findTime [numeric]
Used in `processLineAndAdd` to skip old lines
FileFilter(Filter):
Files-aware Filter
.__logPath [list]
keeps the tracked files (added 1-by-1 using addLogPath)
stored as FileContainer's
.getFailures
actually just returns
True
if managed to open and get lines (until empty)
False
if failed to open or absent container matching the filename
FileContainer
Adapter for a file to deal with log rotation.
.open,.close,.readline
RF-Note: readline returns "" with handler absent... shouldn't it be None?
.__pos
Keeps the position pointer
ipdns.py
~~~~~~~~
DNSUtils
Utility class for DNS handling
IPAddr
Object-class for IP address handling
filter*.py
~~~~~~~~~~
Implementations of FileFilter's for specific backends. Derived
classes should provide an implementation of `run` and usually
override `addLogPath`, `delLogPath` methods. In run() method they all
one way or another provide
try:
while True:
ticket = self.failManager.toBan()
self.jail.putFailTicket(ticket)
except FailManagerEmpty:
self.failManager.cleanup(MyTime.time())
thus channelling "ban tickets" from their failManager to the
corresponding jail.
action.py
~~~~~~~~~
Takes care about executing start/check/ban/unban/stop commands

491
fail2ban-master/FILTERS Normal file
View File

@@ -0,0 +1,491 @@
.. __ _ _ ___ _
/ _|__ _(_) |_ ) |__ __ _ _ _
| _/ _` | | |/ /| '_ \/ _` | ' \
|_| \__,_|_|_/___|_.__/\__,_|_||_|
================================================================================
Developing Filters
================================================================================
Filters are tricky. They need to:
* work with a variety of the versions of the software that generates the logs;
* work with the range of logging configuration options available in the
software;
* work with multiple operating systems;
* not make assumptions about the log format in excess of the software
(e.g. do not assume a username doesn't contain spaces and use \S+ unless
you've checked the source code);
* account for how future versions of the software will log messages
(e.g. guess what would happen to the log message if different authentication
types are added);
* not be susceptible to DoS vulnerabilities (see Filter Security below); and
* match intended log lines only.
Please follow the steps from Filter Test Cases to Developing Filter Regular
Expressions and submit a GitHub pull request (PR) afterwards. If you get stuck,
you can push your unfinished changes and still submit a PR -- describe
what you have done, what is the hurdle, and we'll attempt to help (PR
will be automagically updated with future commits you would push to
complete it).
Filter Test Cases
=================
Purpose
-------
Start by finding the log messages that the application generates related to
some form of authentication failure. If you are adding to an existing filter
think about whether the log messages are of a similar importance and purpose
to the existing filter. If you were a user of Fail2Ban, and did a package
update of Fail2Ban that started matching new log messages, would anything
unexpected happen? Would the bantime/findtime for the jail be appropriate for
the new log messages? If it doesn't, perhaps it needs to be in a separate
filter definition, for example like exim filter aims at authentication failures
and exim-spam at log messages related to spam.
Even if it is a new filter you may consider separating the log messages into
different filters based on purpose.
Cause
-----
Are some of the log lines a result of the same action? For example, is a PAM
failure log message, followed by an application specific failure message the
result of the same user/script action? If you add regular expressions for
both you would end up with two failures for a single action.
Therefore, select the most appropriate log message and document the other log
message) with a test case not to match it and a description as to why you chose
one over another.
With the selected log lines consider what action has caused those log
messages and whether they could have been generated by accident? Could
the log message be occurring due to the first step towards the application
asking for authentication? Could the log messages occur often? If some of
these are true make a note of this in the jail.conf example that you provide.
Samples
-------
It is important to include log file samples so any future change in the regular
expression will still work with the log lines you have identified.
The sample log messages are provided in a file under testcases/files/logs/
named identically as the corresponding filter (but without .conf extension).
Each log line should be preceded by a line with failJSON metadata (so the logs
lines are tested in the test suite) directly above the log line. If there is
any specific information about the log message, such as version or an
application configuration option that is needed for the message to occur,
include this in a comment (line beginning with #) above the failJSON metadata.
Log samples should include only one, definitely not more than 3, examples of
log messages of the same form. If log messages are different in different
versions of the application log messages that show this are encouraged.
Also attempt to inject an IP into the application (e.g. by specifying
it as a username) so that Fail2Ban possibly detects the IP
from user input rather than the true origin. See the Filter Security section
and the top example in testcases/files/logs/apache-auth as to how to do this.
One you have discovered that this is possible, correct the regex so it doesn't
match and provide this as a test case with "match": false (see failJSON below).
If the mechanism to create the log message isn't obvious provide a
configuration and/or sample scripts testcases/files/config/{filtername} and
reference these in the comments above the log line.
FailJSON metadata
-----------------
A failJSON metadata is a comment immediately above the log message. It will
look like::
# failJSON: { "time": "2013-06-10T10:10:59", "match": true , "host": "93.184.216.119" }
Time should match the time of the log message. It is in a specific format of
Year-Month-Day'T'Hour:minute:Second. If your log message does not include a
year, like the example below, the year should be listed as 2005, if before Sun
Aug 14 10am UTC, and 2004 if afterwards. Here is an example failJSON
line preceding a sample log line::
# failJSON: { "time": "2005-03-24T15:25:51", "match": true , "host": "198.51.100.87" }
Mar 24 15:25:51 buffalo1 dropbear[4092]: bad password attempt for 'root' from 198.51.100.87:5543
The "host" in failJSON should contain the IP or domain that should be blocked.
For long lines that you do not want to be matched (e.g. from log injection
attacks) and any log lines to be excluded (see "Cause" section above), set
"match": false in the failJSON and describe the reason in the comment above.
After developing regexes, the following command will test all failJSON metadata
against the log lines in all sample log files::
./fail2ban-testcases testSampleRegex
Developing Filter Regular Expressions
=====================================
Date/Time
---------
At the moment, Fail2Ban depends on log lines to have time stamps. That is why
before starting to develop failregex, check if your log line format is known to
Fail2Ban. Copy the time component from the log line and append an IP address to
test with following command::
./fail2ban-regex "2013-09-19 02:46:12 1.2.3.4" "<HOST>"
Output of such command should contain something like::
Date template hits:
|- [# of hits] date format
| [1] Year-Month-Day Hour:Minute:Second
Ensure that the template description matches time/date elements in your log line
time stamp. If there is no matched format then date template needs to be added
to server/datedetector.py. Ensure that a new template is added in the order
that more specific matches occur first and that there is no confusion between a
Day and a Month.
Filter file
-----------
The filter is specified in a config/filter.d/{filtername}.conf file. Filter file
can have sections INCLUDES (optional) and Definition as follows::
[INCLUDES]
before = common.conf
after = filtername.local
[Definition]
failregex = ....
ignoreregex = ....
This is also documented in the man page jail.conf (section 5). Other definitions
can be added to make failregex's more readable and maintainable to be used
through string Interpolations (see http://docs.python.org/2.7/library/configparser.html)
General rules
-------------
Use "before" if you need to include a common set of rules, like syslog or if
there is a common set of regexes for multiple filters.
Use "after" if you wish to allow the user to overwrite a set of customisations
of the current filter. This file doesn't need to exist.
Try to avoid using ignoreregex mainly for performance reasons. The case when you
would use it is if in trying to avoid using it, you end up with an unreadable
failregex.
Syslog
------
If your application logs to syslog you can take advantage of log line prefix
definitions present in common.conf. So as a base use::
[INCLUDES]
before = common.conf
[Definition]
_daemon = app
failregex = ^%(__prefix_line)s
In this example common.conf defines __prefix_line which also contains the
_daemon name (in syslog terms the service) you have just specified. _daemon
can also be a regex.
For example, to capture following line _daemon should be set to "dovecot"::
Dec 12 11:19:11 dunnart dovecot: pop3-login: Aborted login (tried to use disabled plaintext auth): rip=190.210.136.21, lip=113.212.99.193
and then ``^%(__prefix_line)s`` would match "Dec 12 11:19:11 dunnart dovecot:
". Note it matches the trailing space(s) as well.
Substitutions (AKA string interpolations)
-----------------------------------------
We have used string interpolations in above examples. They are useful for
making the regexes more readable, reuse generic patterns in multiple failregex
lines, and also to refer definition of regex parts to specific filters or even
to the user. General principle is that value of a _name variable replaces
occurrences of %(_name)s within the same section or anywhere in the config file
if defined in [DEFAULT] section.
Regular Expressions
-------------------
Regular expressions (failregex, ignoreregex) assume that the date/time has been
removed from the log line (this is just how fail2ban works internally ATM).
If the format is like '<date...> error 1.2.3.4 is evil' then you need to match
the <> at the start so regex should be similar to '^<> error <HOST> is evil$' using
<HOST> where the IP/domain name appears in the log line.
The following general rules apply to regular expressions:
* ensure regexes are anchored (e. g. start with a ^) and are as restrictive
as possible. E.g. do not use catch-alls .+ or .* if \d+ or [^"]* is sufficient.
Basically avoid the catch-alls where it is possible, especially non-greedy
catch-alls on RE with many branches or ambiguous matches;
* use functionality of Python regexes defined in the standard Python re library
https://docs.python.org/library/re.html;
* try to write regular expressions as efficient as possible. E.g. do not write
several REs for almost the same messages, just with A or B or C, if they can
be matched by single RE using | operator like ...(?:A|B|C)... and order them
by their frequency, so A before B and C, if A is more frequent or will match
faster;
* make regular expressions readable (as much as possible), but only if it is
justified. E.g. (?:...) represents a non-capturing regex and (...) is more
readable, but capturing groups make the RE a bit slower, thus (?:...) may be
more preferable.
If you have only a basic knowledge of regular repressions we advise to read
https://docs.python.org/library/re.html first. It doesn't take long and would
remind you e.g. which characters you need to escape and which you don't.
Developing/testing a regex
--------------------------
You can develop a regex in a file or using command line depending on your
preference. You can also use samples you have already created in the test cases
or test them one at a time.
The general tool for testing Fail2Ban regexes is fail2ban-regex. To see how to
use it run::
./fail2ban-regex --help
Take note of -l heavydebug / -l debug and -v as they might be very useful.
.. TIP::
Take a look at the source code of the application you are developing
failregex for. You may see optional or extra log messages, or parts there
of, that need to form part of your regex. It may also reveal how some
parts are constrained and different formats depending on configuration or
less common usages.
.. TIP::
Some applications log spaces at the end. If you are not sure add \s*$ as
the end part of the regex.
If your regex is not matching, http://www.debuggex.com/?flavor=python can help
to tune it. fail2ban-regex -D ... will present Debuggex URLs for the regexs
and sample log files that you pass into it.
In general use when using regex debuggers for generating fail2ban filters:
* use regex from the ./fail2ban-regex output (to ensure all substitutions are
done)
* replace <HOST> with (?&.ipv4)
* make sure that regex type set to Python
* for the test data put your log output with the date/time removed
When you have fixed the regex put it back into your filter file.
Please spread the good word about Debuggex - Serge Toarca is kindly continuing
its free availability to Open Source developers.
Finishing up
------------
If you've added a new filter, add a new entry in config/jail.conf. The theory
here is that a user will create a jail.local with [filtername]\nenable=true to
enable your jail.
So more specifically in the [filter] section in jail.conf:
* ensure that you have "enabled = false" (users will enable as needed);
* use "filter =" set to your filter name;
* use a typical action to disable ports associated with the application;
* set "logpath" to the usual location of application log file;
* if the default findtime or bantime isn't appropriate to the filter, specify
more appropriate choices (possibly with a brief comment line).
Submit github pull request (See "Pull Requests" above) for
github.com/fail2ban/fail2ban containing your great work.
You may also consider https://github.com/fail2ban/fail2ban/wiki/Best-practice
Filter Security
===============
Poor filter regular expressions are susceptible to DoS attacks.
When a remote user has the ability to introduce text that would match filter's
failregex, while matching inserted text to the <HOST> part, they have the
ability to deny any host they choose.
So the <HOST> part must be anchored on text generated by the application, and
not the user, to an extent sufficient to prevent user inserting the entire text
matching this or any other failregex.
Ideally filter regex should anchor at the beginning and at the end of log line.
However as more applications log at the beginning than the end, anchoring the
beginning is more important. If the log file used by the application is shared
with other applications, like system logs, ensure the other application that use
that log file do not log user generated text at the beginning of the line, or,
if they do, ensure the regexes of the filter are sufficient to mitigate the risk
of insertion.
Examples of poor filters
------------------------
1. Too restrictive
We find a log message::
Apr-07-13 07:08:36 Invalid command fial2ban from 1.2.3.4
We make a failregex::
^Invalid command \S+ from <HOST>
Now think evil. The user does the command 'blah from 1.2.3.44'
The program diligently logs::
Apr-07-13 07:08:36 Invalid command blah from 1.2.3.44 from 1.2.3.4
And fail2ban matches 1.2.3.44 as the IP that it ban. A DoS attack was successful.
The fix here is that the command can be anything so .* is appropriate::
^Invalid command .* from <HOST>
Here the .* will match until the end of the string. Then realise it has more to
match, i.e. "from <HOST>" and go back until it find this. Then it will ban
1.2.3.4 correctly. Since the <HOST> is always at the end, end the regex with a $::
^Invalid command .* from <HOST>$
Note if we'd just had the expression::
^Invalid command \S+ from <HOST>$
Then provided the user put a space in their command they would have never been
banned.
2. Unanchored regex can match other user injected data
From the Apache vulnerability CVE-2013-2178
( original ref: https://vndh.net/note:fail2ban-089-denial-service ).
An example bad regex for Apache::
failregex = [[]client <HOST>[]] user .* not found
Since the user can do a get request on::
GET /[client%20192.168.0.1]%20user%20root%20not%20found HTTP/1.0
Host: remote.site
Now the log line will be::
[Sat Jun 01 02:17:42 2013] [error] [client 192.168.33.1] File does not exist: /srv/http/site/[client 192.168.0.1] user root not found
As this log line doesn't match other expressions hence it matches the above
regex and blocks 192.168.33.1 as a denial of service from the HTTP requester.
3. Over greedy pattern matching
From: https://github.com/fail2ban/fail2ban/pull/426
An example ssh log (simplified)::
Sep 29 17:15:02 spaceman sshd[12946]: Failed password for user from 127.0.0.1 port 20000 ssh1: ruser remoteuser
As we assume username can include anything including spaces its prudent to put
.* here. The remote user can also exist as anything so lets not make assumptions again::
failregex = ^%(__prefix_line)sFailed \S+ for .* from <HOST>( port \d*)?( ssh\d+)?(: ruser .*)?$
So this works. The problem is if the .* after remote user is injected by the
user to be 'from 1.2.3.4'. The resultant log line is::
Sep 29 17:15:02 spaceman sshd[12946]: Failed password for user from 127.0.0.1 port 20000 ssh1: ruser from 1.2.3.4
Testing with::
fail2ban-regex -v 'Sep 29 17:15:02 Failed password for user from 127.0.0.1 port 20000 ssh1: ruser from 1.2.3.4' '^ Failed \S+ for .* from <HOST>( port \d*)?( ssh\d+)?(: ruser .*)?$'
.. TIP:: I've removed the bit that matches __prefix_line from the regex and log.
Shows::
1) [1] ^ Failed \S+ for .* from <HOST>( port \d*)?( ssh\d+)?(: ruser .*)?$
1.2.3.4 Sun Sep 29 17:15:02 2013
It should of matched 127.0.0.1. So the first greedy part of the greedy regex
matched until the end of the string. The was no "from <HOST>" so the regex
engine worked backwards from the end of the string until this was matched.
The result was that 1.2.3.4 was matched, injected by the user, and the wrong IP
was banned.
The solution here is to make the first .* non-greedy with .*?. Here it matches
as little as required and the fail2ban-regex tool shows the output::
fail2ban-regex -v 'Sep 29 17:15:02 Failed password for user from 127.0.0.1 port 20000 ssh1: ruser from 1.2.3.4' '^ Failed \S+ for .*? from <HOST>( port \d*)?( ssh\d+)?(: ruser .*)?$'
1) [1] ^ Failed \S+ for .*? from <HOST>( port \d*)?( ssh\d+)?(: ruser .*)?$
127.0.0.1 Sun Sep 29 17:15:02 2013
So the general case here is a log line that contains::
(fixed_data_1)<HOST>(fixed_data_2)(user_injectable_data)
Where the regex that matches fixed_data_1 is gready and matches the entire
string, before moving backwards and user_injectable_data can match the entire
string.
Another case
------------
ref: https://www.debuggex.com/r/CtAbeKMa2sDBEfA2/0
A webserver logs the following without URL escaping::
[error] 2865#0: *66647 user "xyz" was not found in "/file", client: 1.2.3.1, server: www.host.com, request: "GET ", client: 3.2.1.1, server: fake.com, request: "GET exploited HTTP/3.3", host: "injected.host", host: "www.myhost.com"
regex::
failregex = ^ \[error\] \d+#\d+: \*\d+ user "\S+":? (?:password mismatch|was not found in ".*"), client: <HOST>, server: \S+, request: "\S+ .+ HTTP/\d+\.\d+", host: "\S+"
The .* matches to the end of the string. Finds that it can't continue to match
", client ... so it moves from the back and find that the user injected web URL::
", client: 3.2.1.1, server: fake.com, request: "GET exploited HTTP/3.3", host: "injected.host
In this case there is a fixed host: "www.myhost.com" at the end so the solution
is to anchor the regex at the end with a $.
If this wasn't the case then first .* needed to be made so it didn't capture
beyond <HOST>.
4. Application generates two identical log messages with different meanings
If the application generates the following two messages under different
circumstances::
client <IP>: authentication failed
client <USER>: authentication failed
Then it's obvious that a regex of ``^client <HOST>: authentication
failed$`` will still cause problems if the user can trigger the second
log message with a <USER> of 123.1.1.1.
Here there's nothing to do except request/change the application so it logs
messages differently.

451
fail2ban-master/MANIFEST Normal file
View File

@@ -0,0 +1,451 @@
bin/fail2ban-client
bin/fail2ban-regex
bin/fail2ban-server
bin/fail2ban-testcases
ChangeLog
config/action.d/abuseipdb.conf
config/action.d/apf.conf
config/action.d/apprise.conf
config/action.d/blocklist_de.conf
config/action.d/bsd-ipfw.conf
config/action.d/cloudflare.conf
config/action.d/cloudflare-token.conf
config/action.d/complain.conf
config/action.d/dshield.conf
config/action.d/dummy.conf
config/action.d/firewallcmd-allports.conf
config/action.d/firewallcmd-common.conf
config/action.d/firewallcmd-ipset.conf
config/action.d/firewallcmd-multiport.conf
config/action.d/firewallcmd-new.conf
config/action.d/firewallcmd-rich-logging.conf
config/action.d/firewallcmd-rich-rules.conf
config/action.d/helpers-common.conf
config/action.d/hostsdeny.conf
config/action.d/ipfilter.conf
config/action.d/ipfw.conf
config/action.d/iptables-allports.conf
config/action.d/iptables.conf
config/action.d/iptables-ipset.conf
config/action.d/iptables-ipset-proto4.conf
config/action.d/iptables-ipset-proto6-allports.conf
config/action.d/iptables-ipset-proto6.conf
config/action.d/iptables-multiport.conf
config/action.d/iptables-multiport-log.conf
config/action.d/iptables-new.conf
config/action.d/iptables-xt_recent-echo.conf
config/action.d/ipthreat.conf
config/action.d/mail-buffered.conf
config/action.d/mail.conf
config/action.d/mail-whois-common.conf
config/action.d/mail-whois.conf
config/action.d/mail-whois-lines.conf
config/action.d/mikrotik.conf
config/action.d/mynetwatchman.conf
config/action.d/netscaler.conf
config/action.d/nftables-allports.conf
config/action.d/nftables.conf
config/action.d/nftables-multiport.conf
config/action.d/nginx-block-map.conf
config/action.d/npf.conf
config/action.d/nsupdate.conf
config/action.d/osx-afctl.conf
config/action.d/osx-ipfw.conf
config/action.d/pf.conf
config/action.d/route.conf
config/action.d/sendmail-buffered.conf
config/action.d/sendmail-common.conf
config/action.d/sendmail.conf
config/action.d/sendmail-geoip-lines.conf
config/action.d/sendmail-whois.conf
config/action.d/sendmail-whois-ipjailmatches.conf
config/action.d/sendmail-whois-ipmatches.conf
config/action.d/sendmail-whois-lines.conf
config/action.d/sendmail-whois-matches.conf
config/action.d/shorewall.conf
config/action.d/shorewall-ipset-proto6.conf
config/action.d/smtp.py
config/action.d/symbiosis-blacklist-allports.conf
config/action.d/ufw.conf
config/action.d/xarf-login-attack.conf
config/fail2ban.conf
config/filter.d/3proxy.conf
config/filter.d/apache-auth.conf
config/filter.d/apache-badbots.conf
config/filter.d/apache-botsearch.conf
config/filter.d/apache-common.conf
config/filter.d/apache-fakegooglebot.conf
config/filter.d/apache-modsecurity.conf
config/filter.d/apache-nohome.conf
config/filter.d/apache-noscript.conf
config/filter.d/apache-overflows.conf
config/filter.d/apache-pass.conf
config/filter.d/apache-shellshock.conf
config/filter.d/assp.conf
config/filter.d/asterisk.conf
config/filter.d/bitwarden.conf
config/filter.d/botsearch-common.conf
config/filter.d/centreon.conf
config/filter.d/common.conf
config/filter.d/counter-strike.conf
config/filter.d/courier-auth.conf
config/filter.d/courier-smtp.conf
config/filter.d/cyrus-imap.conf
config/filter.d/dante.conf
config/filter.d/directadmin.conf
config/filter.d/domino-smtp.conf
config/filter.d/dovecot.conf
config/filter.d/dropbear.conf
config/filter.d/drupal-auth.conf
config/filter.d/ejabberd-auth.conf
config/filter.d/exim-common.conf
config/filter.d/exim.conf
config/filter.d/exim-spam.conf
config/filter.d/freeswitch.conf
config/filter.d/froxlor-auth.conf
config/filter.d/gitlab.conf
config/filter.d/grafana.conf
config/filter.d/groupoffice.conf
config/filter.d/gssftpd.conf
config/filter.d/guacamole.conf
config/filter.d/haproxy-http-auth.conf
config/filter.d/horde.conf
config/filter.d/ignorecommands/apache-fakegooglebot
config/filter.d/kerio.conf
config/filter.d/lighttpd-auth.conf
config/filter.d/mongodb-auth.conf
config/filter.d/monit.conf
config/filter.d/monitorix.conf
config/filter.d/mssql-auth.conf
config/filter.d/murmur.conf
config/filter.d/mysqld-auth.conf
config/filter.d/nagios.conf
config/filter.d/named-refused.conf
config/filter.d/nginx-bad-request.conf
config/filter.d/nginx-botsearch.conf
config/filter.d/nginx-error-common.conf
config/filter.d/nginx-forbidden.conf
config/filter.d/nginx-http-auth.conf
config/filter.d/nginx-limit-req.conf
config/filter.d/nsd.conf
config/filter.d/openhab.conf
config/filter.d/openwebmail.conf
config/filter.d/oracleims.conf
config/filter.d/pam-generic.conf
config/filter.d/perdition.conf
config/filter.d/phpmyadmin-syslog.conf
config/filter.d/php-url-fopen.conf
config/filter.d/portsentry.conf
config/filter.d/postfix.conf
config/filter.d/proftpd.conf
config/filter.d/pure-ftpd.conf
config/filter.d/qmail.conf
config/filter.d/recidive.conf
config/filter.d/roundcube-auth.conf
config/filter.d/routeros-auth.conf
config/filter.d/scanlogd.conf
config/filter.d/screensharingd.conf
config/filter.d/selinux-common.conf
config/filter.d/selinux-ssh.conf
config/filter.d/sendmail-auth.conf
config/filter.d/sendmail-reject.conf
config/filter.d/sieve.conf
config/filter.d/slapd.conf
config/filter.d/softethervpn.conf
config/filter.d/sogo-auth.conf
config/filter.d/solid-pop3d.conf
config/filter.d/squid.conf
config/filter.d/squirrelmail.conf
config/filter.d/sshd.conf
config/filter.d/stunnel.conf
config/filter.d/suhosin.conf
config/filter.d/tine20.conf
config/filter.d/traefik-auth.conf
config/filter.d/uwimap-auth.conf
config/filter.d/vsftpd.conf
config/filter.d/webmin-auth.conf
config/filter.d/wuftpd.conf
config/filter.d/xinetd-fail.conf
config/filter.d/znc-adminlog.conf
config/filter.d/zoneminder.conf
config/jail.conf
config/paths-arch.conf
config/paths-common.conf
config/paths-debian.conf
config/paths-fedora.conf
config/paths-freebsd.conf
config/paths-opensuse.conf
config/paths-osx.conf
CONTRIBUTING.md
COPYING
.coveragerc
DEVELOP
fail2ban/client/actionreader.py
fail2ban/client/beautifier.py
fail2ban/client/configparserinc.py
fail2ban/client/configreader.py
fail2ban/client/configurator.py
fail2ban/client/csocket.py
fail2ban/client/fail2banclient.py
fail2ban/client/fail2bancmdline.py
fail2ban/client/fail2banreader.py
fail2ban/client/fail2banregex.py
fail2ban/client/fail2banserver.py
fail2ban/client/filterreader.py
fail2ban/client/__init__.py
fail2ban/client/jailreader.py
fail2ban/client/jailsreader.py
fail2ban/compat/asynchat.py
fail2ban/compat/asyncore.py
fail2ban/exceptions.py
fail2ban/helpers.py
fail2ban/__init__.py
fail2ban/protocol.py
fail2ban/server/action.py
fail2ban/server/actions.py
fail2ban/server/asyncserver.py
fail2ban/server/banmanager.py
fail2ban/server/database.py
fail2ban/server/datedetector.py
fail2ban/server/datetemplate.py
fail2ban/server/failmanager.py
fail2ban/server/failregex.py
fail2ban/server/filterpoll.py
fail2ban/server/filter.py
fail2ban/server/filterpyinotify.py
fail2ban/server/filtersystemd.py
fail2ban/server/__init__.py
fail2ban/server/ipdns.py
fail2ban/server/jail.py
fail2ban/server/jails.py
fail2ban/server/jailthread.py
fail2ban/server/mytime.py
fail2ban/server/observer.py
fail2ban/server/server.py
fail2ban/server/strptime.py
fail2ban/server/ticket.py
fail2ban/server/transmitter.py
fail2ban/server/utils.py
fail2ban/setup.py
fail2ban-testcases-all
fail2ban-testcases-all-python3
fail2ban/tests/action_d/__init__.py
fail2ban/tests/action_d/test_smtp.py
fail2ban/tests/actionstestcase.py
fail2ban/tests/actiontestcase.py
fail2ban/tests/banmanagertestcase.py
fail2ban/tests/clientbeautifiertestcase.py
fail2ban/tests/clientreadertestcase.py
fail2ban/tests/config/action.d/action.conf
fail2ban/tests/config/action.d/brokenaction.conf
fail2ban/tests/config/fail2ban.conf
fail2ban/tests/config/filter.d/checklogtype.conf
fail2ban/tests/config/filter.d/checklogtype_test.conf
fail2ban/tests/config/filter.d/simple.conf
fail2ban/tests/config/filter.d/test.conf
fail2ban/tests/config/filter.d/test.local
fail2ban/tests/config/filter.d/zzz-generic-example.conf
fail2ban/tests/config/filter.d/zzz-sshd-obsolete-multiline.conf
fail2ban/tests/config/jail.conf
fail2ban/tests/databasetestcase.py
fail2ban/tests/datedetectortestcase.py
fail2ban/tests/dummyjail.py
fail2ban/tests/fail2banclienttestcase.py
fail2ban/tests/fail2banregextestcase.py
fail2ban/tests/failmanagertestcase.py
fail2ban/tests/files/action.d/action_checkainfo.py
fail2ban/tests/files/action.d/action_errors.py
fail2ban/tests/files/action.d/action_modifyainfo.py
fail2ban/tests/files/action.d/action_noAction.py
fail2ban/tests/files/action.d/action_nomethod.py
fail2ban/tests/files/action.d/action.py
fail2ban/tests/files/config/apache-auth/basic/authz_owner/cant_get_me.html
fail2ban/tests/files/config/apache-auth/basic/authz_owner/.htaccess
fail2ban/tests/files/config/apache-auth/basic/authz_owner/.htpasswd
fail2ban/tests/files/config/apache-auth/basic/file/.htaccess
fail2ban/tests/files/config/apache-auth/basic/file/.htpasswd
fail2ban/tests/files/config/apache-auth/digest_anon/.htaccess
fail2ban/tests/files/config/apache-auth/digest_anon/.htpasswd
fail2ban/tests/files/config/apache-auth/digest/.htaccess
fail2ban/tests/files/config/apache-auth/digest/.htpasswd
fail2ban/tests/files/config/apache-auth/digest.py
fail2ban/tests/files/config/apache-auth/digest_time/.htaccess
fail2ban/tests/files/config/apache-auth/digest_time/.htpasswd
fail2ban/tests/files/config/apache-auth/digest_wrongrelm/.htaccess
fail2ban/tests/files/config/apache-auth/digest_wrongrelm/.htpasswd
fail2ban/tests/files/config/apache-auth/noentry/.htaccess
fail2ban/tests/files/config/apache-auth/README
fail2ban/tests/files/database_v1.db
fail2ban/tests/files/database_v2.db
fail2ban/tests/files/filter.d/substitution.conf
fail2ban/tests/files/filter.d/testcase01.conf
fail2ban/tests/files/filter.d/testcase02.conf
fail2ban/tests/files/filter.d/testcase02.local
fail2ban/tests/files/filter.d/testcase-common.conf
fail2ban/tests/files/ignorecommand.py
fail2ban/tests/files/logs/3proxy
fail2ban/tests/files/logs/apache-auth
fail2ban/tests/files/logs/apache-badbots
fail2ban/tests/files/logs/apache-botsearch
fail2ban/tests/files/logs/apache-fakegooglebot
fail2ban/tests/files/logs/apache-modsecurity
fail2ban/tests/files/logs/apache-nohome
fail2ban/tests/files/logs/apache-noscript
fail2ban/tests/files/logs/apache-overflows
fail2ban/tests/files/logs/apache-pass
fail2ban/tests/files/logs/apache-shellshock
fail2ban/tests/files/logs/assp
fail2ban/tests/files/logs/asterisk
fail2ban/tests/files/logs/bitwarden
fail2ban/tests/files/logs/bsd/syslog-plain.txt
fail2ban/tests/files/logs/bsd/syslog-v.txt
fail2ban/tests/files/logs/bsd/syslog-vv.txt
fail2ban/tests/files/logs/centreon
fail2ban/tests/files/logs/counter-strike
fail2ban/tests/files/logs/courier-auth
fail2ban/tests/files/logs/courier-smtp
fail2ban/tests/files/logs/cyrus-imap
fail2ban/tests/files/logs/dante
fail2ban/tests/files/logs/directadmin
fail2ban/tests/files/logs/domino-smtp
fail2ban/tests/files/logs/dovecot
fail2ban/tests/files/logs/dropbear
fail2ban/tests/files/logs/drupal-auth
fail2ban/tests/files/logs/ejabberd-auth
fail2ban/tests/files/logs/exim
fail2ban/tests/files/logs/exim-spam
fail2ban/tests/files/logs/freeswitch
fail2ban/tests/files/logs/froxlor-auth
fail2ban/tests/files/logs/gitlab
fail2ban/tests/files/logs/grafana
fail2ban/tests/files/logs/groupoffice
fail2ban/tests/files/logs/gssftpd
fail2ban/tests/files/logs/guacamole
fail2ban/tests/files/logs/haproxy-http-auth
fail2ban/tests/files/logs/horde
fail2ban/tests/files/logs/kerio
fail2ban/tests/files/logs/lighttpd-auth
fail2ban/tests/files/logs/mongodb-auth
fail2ban/tests/files/logs/monit
fail2ban/tests/files/logs/monitorix
fail2ban/tests/files/logs/mssql-auth
fail2ban/tests/files/logs/murmur
fail2ban/tests/files/logs/mysqld-auth
fail2ban/tests/files/logs/nagios
fail2ban/tests/files/logs/named-refused
fail2ban/tests/files/logs/nginx-bad-request
fail2ban/tests/files/logs/nginx-botsearch
fail2ban/tests/files/logs/nginx-forbidden
fail2ban/tests/files/logs/nginx-http-auth
fail2ban/tests/files/logs/nginx-limit-req
fail2ban/tests/files/logs/nsd
fail2ban/tests/files/logs/openhab
fail2ban/tests/files/logs/openwebmail
fail2ban/tests/files/logs/oracleims
fail2ban/tests/files/logs/pam-generic
fail2ban/tests/files/logs/perdition
fail2ban/tests/files/logs/phpmyadmin-syslog
fail2ban/tests/files/logs/php-url-fopen
fail2ban/tests/files/logs/portsentry
fail2ban/tests/files/logs/postfix
fail2ban/tests/files/logs/proftpd
fail2ban/tests/files/logs/pure-ftpd
fail2ban/tests/files/logs/qmail
fail2ban/tests/files/logs/recidive
fail2ban/tests/files/logs/roundcube-auth
fail2ban/tests/files/logs/routeros-auth
fail2ban/tests/files/logs/scanlogd
fail2ban/tests/files/logs/screensharingd
fail2ban/tests/files/logs/selinux-ssh
fail2ban/tests/files/logs/sendmail-auth
fail2ban/tests/files/logs/sendmail-reject
fail2ban/tests/files/logs/sieve
fail2ban/tests/files/logs/slapd
fail2ban/tests/files/logs/softethervpn
fail2ban/tests/files/logs/sogo-auth
fail2ban/tests/files/logs/solid-pop3d
fail2ban/tests/files/logs/squid
fail2ban/tests/files/logs/squirrelmail
fail2ban/tests/files/logs/sshd
fail2ban/tests/files/logs/sshd-journal
fail2ban/tests/files/logs/stunnel
fail2ban/tests/files/logs/suhosin
fail2ban/tests/files/logs/tine20
fail2ban/tests/files/logs/traefik-auth
fail2ban/tests/files/logs/uwimap-auth
fail2ban/tests/files/logs/vsftpd
fail2ban/tests/files/logs/webmin-auth
fail2ban/tests/files/logs/wuftpd
fail2ban/tests/files/logs/xinetd-fail
fail2ban/tests/files/logs/znc-adminlog
fail2ban/tests/files/logs/zoneminder
fail2ban/tests/files/logs/zzz-generic-example
fail2ban/tests/files/logs/zzz-sshd-obsolete-multiline
fail2ban/tests/files/testcase01a.log
fail2ban/tests/files/testcase01.log
fail2ban/tests/files/testcase02.log
fail2ban/tests/files/testcase03.log
fail2ban/tests/files/testcase04.log
fail2ban/tests/files/testcase-journal.log
fail2ban/tests/files/testcase-multiline.log
fail2ban/tests/files/testcase-usedns.log
fail2ban/tests/files/testcase-wrong-char.log
fail2ban/tests/files/zzz-sshd-obsolete-multiline.log
fail2ban/tests/filtertestcase.py
fail2ban/tests/__init__.py
fail2ban/tests/misctestcase.py
fail2ban/tests/observertestcase.py
fail2ban/tests/samplestestcase.py
fail2ban/tests/servertestcase.py
fail2ban/tests/sockettestcase.py
fail2ban/tests/tickettestcase.py
fail2ban/tests/utils.py
fail2ban/version.py
files/bash-completion
files/cacti/cacti_host_template_fail2ban.xml
files/cacti/fail2ban_stats.sh
files/cacti/README
files/debian-initd
files/fail2ban-logrotate
files/fail2ban-openrc.conf
files/fail2ban-openrc.init.in
files/fail2ban.service.in
files/fail2ban-tmpfiles.conf
files/fail2ban.upstart
files/gen_badbots
files/ipmasq-ZZZzzz_fail2ban.rul
files/logwatch/fail2ban
files/logwatch/fail2ban-0.8.log
files/logwatch/fail2ban-0.9.log
files/macosx-initd
files/monit/fail2ban
files/nagios/check_fail2ban
files/nagios/README
files/redhat-initd
files/solaris-fail2ban.xml
files/solaris-svc-fail2ban
files/suse-initd
FILTERS
kill-server
man/fail2ban.1
man/fail2ban-client.1
man/fail2ban-client.h2m
man/fail2ban-python.1
man/fail2ban-python.h2m
man/fail2ban-regex.1
man/fail2ban-regex.h2m
man/fail2ban-server.1
man/fail2ban-server.h2m
man/fail2ban-testcases.1
man/fail2ban-testcases.h2m
man/generate-man
man/jail.conf.5
.pylintrc
README.md
README.Solaris
RELEASE
setup.cfg
setup.py
THANKS
TODO
Vagrantfile

View File

@@ -0,0 +1,5 @@
include ChangeLog COPYING DEVELOP FILTERS README.* THANKS TODO CONTRIBUTING* Vagrantfile
graft doc
graft files
recursive-include config *.conf *.py
recursive-include config/filter.d/ignorecommands *

View File

@@ -0,0 +1,122 @@
# vim:tw=80:ft=txt
README FOR SOLARIS INSTALLATIONS
By Roy Sigurd Karlsbakk <roy@karlsbakk.net>
ABOUT
This README is meant for those wanting to install fail2ban on Solaris 10,
OpenSolaris, OpenIndiana etc. To some degree it may as well be useful for
users of older Solaris versions and Nexenta, but don't rely on it.
READ ME FIRST
If I use the term Solaris, I am talking about any Solaris dialect, that is, the
official Sun/Oracle ones or derivatives. If I describe an OS as
"OpenSolaris-based", it means it's either OpenSolaris, OpenIndiana or one of the
other, but /not/ the Nexenta family, since this only uses the OpenSolaris/
IllumOS kernel and not the userland. If I say Solaris 10, I mean Solaris 10 and
perhaps, if you're lucky and have some good gods on your side, it may also apply
to Solaris 9 or even 8 and hopefully in the new Solaris 11 whenever that may be
released. Quoted lines of code, settings etc. are indented with two spaces.
This does _not_ mean you should use that indentation, especially in config files
where they can be harmful. Optional settings are prefixed with OPT: while
required settings are prefixed with REQ:. If no prefix is found, regard it as a
required setting.
INSTALLATION ON SOLARIS
The installation is straight forward on Solaris as well as on linux/bsd/etc.
./setup.py install installs the general packages in /usr/bin on OpenSolaris-
based distros or (at least on this box) under /usr/sfw/bin on Solaris 10. In
the files/ directory you will find the file solaris-fail2ban.xml containing the
Solaris service. To install this, run the following command as root (or with
sudo):
svccfg import files/solaris-fail2ban.xml
This should normally without giving an error. If you get an error, deal with it,
and please post any relevant info (or fixes?) to the fail2ban mailing list.
Next install the service handler - copy the script in and allow it to be executed:
cp files/solaris-svc-fail2ban /lib/svc/method/svc-fail2ban
chmod +x /lib/svc/method/svc-fail2ban
CONFIGURE SYSLOG
For some reason, a default Solaris installation does not log ssh login attempts,
and since fail2ban works by monitoring logs, enabling this logging is rather
important for it to work. To enable this, edit /etc/syslog.conf and add a line
at the end:
auth.info /var/adm/auth.log
Save the file and exit, and run
touch /var/adm/auth.log
The Solaris system logger will _not_ create a non-existing file. Now, restart
the system logger.
svcadm restart system-log
Try to ssh into localhost with ssh asdf@localhost and enter an invalid password.
Make sure this is logged in the above file. When done, you may configure
fail2ban.
FAIL2BAN CONFIGURATION
OPT: Create /etc/fail2ban/fail2ban.local containing:
# Fail2Ban configuration file for logging fail2ban on Solaris
#
[Definition]
logtarget = /var/adm/fail2ban.log
REQ: Create /etc/fail2ban/jail.local containing:
[ssh-tcpwrapper]
enabled = true
filter = sshd
action = hostsdeny[daemon_list=sshd]
sendmail-whois[name=SSH, dest=you@example.com]
ignoreregex = for myuser from
logpath = /var/adm/auth.log
Set the sendmail dest address to something useful or drop the line to stop it spamming you.
Set 'myuser' to your username to avoid banning yourself or remove the line.
START (OR RESTART) FAIL2BAN
Enable the fail2ban service with
svcadm enable fail2ban
When done, check that all services are running well
svcs -xv
GOTCHAS AND FIXMES
* It seems the installation may be starting fail2ban automatically. If this is
done, fail2ban will not start, but no errors will be returned from svcs
(above). Check if it's running with 'ps -ef | grep fail2ban' and manually kill
the PID if it is. Re-enable fail2ban and try again
svcadm disable fail2ban
svcadm enable fail2ban
* If svcs -xv says that fail2ban failed to start or svcs says it's in maintenance mode
check /var/svc/log/network-fail2ban:default.log for clues.
Check permissions on /var/adm, /var/adm/auth.log /var/adm/fail2ban.log and /var/run/fail2ban
You may need to:
sudo mkdir /var/run/fail2ban
* Fail2ban adds lines like these to /etc/hosts.deny:
sshd: 1.2.3.4

126
fail2ban-master/README.md Normal file
View File

@@ -0,0 +1,126 @@
__ _ _ ___ _
/ _|__ _(_) |_ ) |__ __ _ _ _
| _/ _` | | |/ /| '_ \/ _` | ' \
|_| \__,_|_|_/___|_.__/\__,_|_||_|
v1.1.0.dev1 20??/??/??
## Fail2Ban: ban hosts that cause multiple authentication errors
Fail2Ban scans log files like `/var/log/auth.log` and bans IP addresses conducting
too many failed login attempts. It does this by updating system firewall rules
to reject new connections from those IP addresses, for a configurable amount
of time. Fail2Ban comes out-of-the-box ready to read many standard log files,
such as those for sshd and Apache, and is easily configured to read any log
file of your choosing, for any error you wish.
Though Fail2Ban is able to reduce the rate of incorrect authentication
attempts, it cannot eliminate the risk presented by weak authentication.
Set up services to use only two factor, or public/private authentication
mechanisms if you really want to protect services.
<img src="http://www.worldipv6launch.org/wp-content/themes/ipv6/downloads/World_IPv6_launch_logo.svg" style="height:52pt;"/> | Since v0.10 fail2ban supports the matching of IPv6 addresses.
------|------
This README is a quick introduction to Fail2Ban. More documentation, FAQ, and HOWTOs
to be found on fail2ban(1) manpage, [Wiki](https://github.com/fail2ban/fail2ban/wiki),
[Developers documentation](https://fail2ban.readthedocs.io/)
and the website: https://www.fail2ban.org
Installation:
-------------
Fail2Ban is likely already packaged for your Linux distribution and [can be installed with a simple command](https://github.com/fail2ban/fail2ban/wiki/How-to-install-fail2ban-packages).
If your distribution is not listed, you can install from GitHub:
Required:
- [Python >= 3.5](https://www.python.org) or [PyPy3](https://pypy.org)
- python-setuptools (or python3-setuptools) for installation from source
Optional:
- [pyinotify >= 0.8.3](https://github.com/seb-m/pyinotify), may require:
* Linux >= 2.6.13
- [systemd >= 204](http://www.freedesktop.org/wiki/Software/systemd) and python bindings:
* [python-systemd package](https://www.freedesktop.org/software/systemd/python-systemd/index.html)
- [dnspython](http://www.dnspython.org/)
- [pyasyncore](https://pypi.org/project/pyasyncore/) and [pyasynchat](https://pypi.org/project/pyasynchat/) (normally bundled-in within fail2ban, for python 3.12+ only)
To install:
tar xvfj fail2ban-master.tar.bz2
cd fail2ban-master
sudo python setup.py install
Alternatively, you can clone the source from GitHub to a directory of your choice, and do the install from there. Pick the correct branch, for example, master or 0.11
git clone https://github.com/fail2ban/fail2ban.git
cd fail2ban
sudo python setup.py install
This will install Fail2Ban into the python library directory. The executable
scripts are placed into `/usr/bin`, and configuration in `/etc/fail2ban`.
Fail2Ban should be correctly installed now. Just type:
fail2ban-client -h
to see if everything is alright. You should always use fail2ban-client and
never call fail2ban-server directly.
You can verify that you have the correct version installed with
fail2ban-client version
Please note that the system init/service script is not automatically installed.
To enable fail2ban as an automatic service, simply copy the script for your
distro from the `files` directory to `/etc/init.d`. Example (on a Debian-based
system):
cp files/debian-initd /etc/init.d/fail2ban
update-rc.d fail2ban defaults
service fail2ban start
Configuration:
--------------
You can configure Fail2Ban using the files in `/etc/fail2ban`. It is possible to
configure the server using commands sent to it by `fail2ban-client`. The
available commands are described in the fail2ban-client(1) manpage. Also see
fail2ban(1) and jail.conf(5) manpages for further references.
Code status:
------------
* [![CI](https://github.com/fail2ban/fail2ban/actions/workflows/main.yml/badge.svg)](https://github.com/fail2ban/fail2ban/actions/workflows/main.yml)
Contact:
--------
### Bugs, feature requests, discussions?
See [CONTRIBUTING.md](https://github.com/fail2ban/fail2ban/blob/master/CONTRIBUTING.md)
### You just appreciate this program:
Send kudos to the original author ([Cyril Jaquier](mailto:cyril.jaquier@fail2ban.org))
or *better* to the [mailing list](https://lists.sourceforge.net/lists/listinfo/fail2ban-users)
since Fail2Ban is "community-driven" for years now.
Thanks:
-------
See [THANKS](https://github.com/fail2ban/fail2ban/blob/master/THANKS) file.
License:
--------
Fail2Ban is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
Fail2Ban is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
Fail2Ban; if not, write to the Free Software Foundation, Inc., 51 Franklin
Street, Fifth Floor, Boston, MA 02110, USA

206
fail2ban-master/RELEASE Normal file
View File

@@ -0,0 +1,206 @@
.. __ _ _ ___ _
/ _|__ _(_) |_ ) |__ __ _ _ _
| _/ _` | | |/ /| '_ \/ _` | ' \
|_| \__,_|_|_/___|_.__/\__,_|_||_|
================================================================================
How to do a release for Fail2Ban
================================================================================
Preparation
===========
* Check distribution patches and see if they can be included
* https://apps.fedoraproject.org/packages/fail2ban/sources
* https://gitweb.gentoo.org/repo/gentoo.git/tree/net-analyzer/fail2ban
* http://svnweb.freebsd.org/ports/head/security/py-fail2ban/
* https://build.opensuse.org/package/show?package=fail2ban&project=openSUSE%3AFactory
* http://sophie.zarb.org/sources/fail2ban (Mageia)
* https://trac.macports.org/browser/trunk/dports/security/fail2ban
* Check distribution outstanding bugs
* https://github.com/fail2ban/fail2ban/issues?sort=updated&state=open
* http://bugs.debian.org/cgi-bin/pkgreport.cgi?dist=unstable;package=fail2ban
* https://bugs.launchpad.net/ubuntu/+source/fail2ban
* http://bugs.sabayon.org/buglist.cgi?quicksearch=net-analyzer%2Ffail2ban
* https://bugs.archlinux.org/?project=5&cat%5B%5D=33&string=fail2ban
* https://bugs.gentoo.org/buglist.cgi?query_format=advanced&short_desc=fail2ban&bug_status=UNCONFIRMED&bug_status=CONFIRMED&bug_status=IN_PROGRESS&short_desc_type=allwords
* https://bugzilla.redhat.com/buglist.cgi?query_format=advanced&bug_status=NEW&bug_status=ASSIGNED&component=fail2ban&classification=Red%20Hat&classification=Fedora
* http://www.freebsd.org/cgi/query-pr-summary.cgi?text=fail2ban
* https://bugs.mageia.org/buglist.cgi?quicksearch=fail2ban
* https://build.opensuse.org/package/requests/openSUSE:Factory/fail2ban
* Make sure the tests pass::
./fail2ban-testcases-all
* Ensure the version is correct in:
* ./fail2ban/version.py
* top of ChangeLog
* README.md
* Ensure the MANIFEST is complete
ad-hoc bash script to run in a clean clone:
find -type f | grep -v -e '\.git' -e '/doc/' -e MANIFEST | sed -e 's,^\./,,g' | while read f; do grep -ne "^$f\$" MANIFEST >/dev/null || echo "$f" ; done
or an alternative for comparison with previous release
git diff 0.10.0 | grep -B2 'index 0000000..' | grep -B1 'new file mode' | sed -n -e '/^diff /s,.* b/,,gp' >> MANIFEST
sort MANIFEST | uniq | sponge MANIFEST
* Run::
python setup.py sdist
* Look for errors like::
'testcases/files/logs/mysqld.log' not a regular file -- skipping
* Which indicates that testcases/files/logs/mysqld.log has been moved or is a directory::
tar -C /tmp -jxf dist/fail2ban-0.9.6.tar.bz2
* clean up current directory::
diff -rul --exclude \*.pyc . /tmp/fail2ban-0.10.0/
* Only differences should be files that you don't want distributed.
* Ensure the tests work from the tarball::
cd /tmp/fail2ban-0.9.6/ && bin/fail2ban-testcases
* Add/finalize the corresponding entry in the ChangeLog
* To generate a list of committers use e.g.::
git shortlog -sn 0.10.0.. | sed -e 's,^[ 0-9\t]*,,g' | tr '\n' '\|' | sed -e 's:|:, :g'
* Ensure the top of the ChangeLog has the right version and current date.
* Ensure the top entry of the ChangeLog has the right version and current date.
* Update man pages::
(cd man ; ./generate-man )
git commit -m 'DOC/ENH: update man pages for release' man/*
* Cleanout TODO file with the finished stuff
* Prepare source and rpm binary distributions::
python setup.py sdist
* Broken for now: python setup.py bdist_rpm
* Broken for now: python setup.py upload
* Tag the release by using a signed (and annotated) tag. Cut/paste
release ChangeLog entry as tag annotation::
git tag -s 0.10.0
Pre Release
===========
* Provide a release sample to distributors
* Arch Linux:
* https://www.archlinux.org/packages/extra/any/fail2ban/
* Debian: Yaroslav Halchenko <debian@onerussian.com>
* http://packages.qa.debian.org/f/fail2ban.html
* FreeBSD: Christoph Theis theis@gmx.at>
* http://svnweb.freebsd.org/ports/head/security/py-fail2ban/Makefile?view=markup
* http://www.freebsd.org/cgi/query-pr-summary.cgi?text=fail2ban
* Fedora: Axel Thimm <Axel.Thimm@atrpms.net>
* https://apps.fedoraproject.org/packages/fail2ban
* http://pkgs.fedoraproject.org/cgit/fail2ban.git
* https://admin.fedoraproject.org/pkgdb/acls/bugs/fail2ban
* Gentoo: netmon@gentoo.org
* https://gitweb.gentoo.org/repo/gentoo.git/tree/net-analyzer/fail2ban/metadata.xml
* https://bugs.gentoo.org/buglist.cgi?quicksearch=fail2ban
* openSUSE: Stephan Kulow <coolo@suse.com>
* https://build.opensuse.org/package/show/openSUSE:Factory/fail2ban
* Mac Ports: @Malbrouck on github (gh-49)
* https://trac.macports.org/browser/trunk/dports/security/fail2ban/Portfile
* Mageia:
* https://bugs.mageia.org/buglist.cgi?quicksearch=fail2ban
* And potentially to the fail2ban-users email list.
* Wait for feedback from distributors
* Prepare a release notice https://github.com/fail2ban/fail2ban/releases/new
* Upload the source/binaries from the dist directory and tag the release using the URL
* Upload source/binaries to sourceforge http://sourceforge.net/projects/fail2ban/
* Run the following and update the wiki with output::
python -c 'import fail2ban.protocol; fail2ban.protocol.printWiki()'
* page: http://www.fail2ban.org/wiki/index.php/Commands
* Update:
* http://www.fail2ban.org/wiki/index.php?title=Template:Fail2ban_Versions&action=edit
* http://www.fail2ban.org/wiki/index.php?title=Template:Fail2ban_News&action=edit
* move old bits to http://www.fail2ban.org/wiki/index.php?title=Template:Fail2ban_OldNews&action=edit
* http://www.fail2ban.org/wiki/index.php/ChangeLog
* http://www.fail2ban.org/wiki/index.php/Requirements (Check requirement)
* http://www.fail2ban.org/wiki/index.php/Features
* See if any filters are upgraded:
http://www.fail2ban.org/wiki/index.php/Special:AllPages
* Email users and development list of release
* notify distributors
Post Release
============
Add the following to the top of the ChangeLog::
ver. 0.10.0 (2016/XX/XXX) - wanna-be-released
-----------
### Fixes
### New Features
### Enhancements
Alter the git shortlog command in the previous section to refer to the just
released version.
and adjust fail2ban/version.py to carry .dev0 suffix to signal
a version under development.

142
fail2ban-master/THANKS Normal file
View File

@@ -0,0 +1,142 @@
Fail2Ban is an open source project which was conceived and originally
developed by Cyril Jaquier until 2010. Since then Fail2Ban grew into
a community-driven project with many contributions from its users.
Below is an alphabetically sorted partial list of the contributors to
the project. If you have been left off, please let us know
(preferably send a pull request on github with the "fix") and you will
be added
Aaron Brice
Adam Tkac
Adrien Clerc
ache
ag4ve (Shawn)
Alasdair D. Campbell
Alexander Koeppe (IPv6 support)
Alexandre Perrin (kAworu)
Amir Caspi
Amy
Andrew James Collett (ajcollett)
Andrew St. Jean
Andrey G. Grozin
Andy Fragen
Arturo 'Buanzo' Busleiman
Axel Thimm
Balazs Mateffy
Bas van den Dikkenberg
Beau Raines
Bill Heaton
Carlos Alberto Lopez Perez
cepheid666
Christian Rauch
Christophe Carles
Christoph Haas
Christos Psonis
craneworks
Cyril Jaquier
Daniel Aleksandersen
Daniel B. Cid
Daniel B.
Daniel Black
David Nutter
David Reagan (jerrac)
Derek Atkins
Donald Yandt
Eric Gerbier
Enrico Labedzki
Eugene Hopkinson (SlowRiot)
ftoppi
Florian Robert (1technophile)
François Boulogne
Frantisek Sumsal
Frédéric
Georgiy Mernov
Guilhem Lettron
Guillaume Delvit
Hank Leininger
Hanno 'Rince' Wagner
Helmut Grohne
Iain Lea
Ioan Indreias
Ivo Truxa
John Thoe
Jacques Lav!gnotte
Johannes Weberhofer
Jason H Martin
Jeaye Wilkerson
Jisoo Park
Joel M Snyder
Jonathan Kamens
Jonathan Lanning
Jonathan Underwood
Joël Bertrand
JP Espinosa
jserrachinha
Justin Shore
Kevin Locke
Kévin Drapel
kjohnsonecl
kojiro
Lars Kneschke
Lee Clemens
leftyfb (Mike Rushton)
M. Maraun
Manuel Arostegui Ramirez
Marcel Dopita
Mark Edgington
Mark McKinstry
Mark White
Markus Hoffmann
Marvin Rouge
mEDI
Мернов Георгий
Merijn Schering
Michael C. Haller
Michael Hanselmann
Mika (mkl)
Nick Munger
onorua
Orion Poplawski
Pablo Rodriguez Fernandez
Paul Marrapese
Paul Traina
Noel Butler
Patrick Börjesson
Pressy
Raphaël Marichez
RealRancor
René Berber
Robert Edeker
Rolf Fokkens
Roman Gelfand
Russell Odom
SATO Kentaro
Sean DuBois
Sebastian Arcus
Serg G. Brester (sebres)
Sergey Safarov
Shaun C.
Sireyessire
silviogarbes
Stefan Tatschner
Stephen Gildea
Steven Hiscocks
TESTOVIK
Thomas Mayer
Tom Pike
Tom Hendrikx
Tomas Pihl
Thomas Skierlo (phaleas)
Tony Lawrence
Tomasz Ciolek
Tyler
Vaclav Misek
Vincent Deffontaines
Yaroslav Halchenko
Winston Smith
Yehuda Katz
ykimon
Yung-Chin Oei
Zbigniew Jędrzejewski-Szmek
zugeschmiert
Zurd

32
fail2ban-master/TODO Normal file
View File

@@ -0,0 +1,32 @@
__ _ _ ___ _
/ _|__ _(_) |_ ) |__ __ _ _ _
| _/ _` | | |/ /| '_ \/ _` | ' \
|_| \__,_|_|_/___|_.__/\__,_|_||_|
================================================================================
ToDo
================================================================================
Legend:
- not yet done
? maybe
# partially done
* done
- Added <USER> tag for failregex. Add features using this information. Maybe add
more tags
- Look at the memory consumption. Decrease memory usage
- More detailed statistics
- Auto-enable function (search for log files), check modification date to see if
service is still in use
- Better handling of the protocol in transmitter.py
- Add gettext support (I18N)
# improve documentation and website for user
# better return values in function

30
fail2ban-master/Vagrantfile vendored Normal file
View File

@@ -0,0 +1,30 @@
Vagrant.configure("2") do |config|
config.vm.define "secure" do |secure|
secure.vm.box = "ubuntu/trusty64"
secure.vm.hostname = "secure.dev.fail2ban.org"
secure.vm.network "private_network", ip: "192.168.200.100"
# secure.vm.synced_folder 'salt/roots', '/srv/salt'
# secure.vm.provision :salt do |salt|
# salt.minion_config = 'salt/minion'
# salt.run_highstate = true
# salt.verbose = true
# end
end
config.vm.define "attacker" do |attacker|
attacker.vm.box = "ubuntu/trusty64"
attacker.vm.hostname = "attacker.dev.fail2ban.org"
attacker.vm.network "private_network", ip: "192.168.200.150"
# attacker.vm.synced_folder 'salt/roots', '/srv/salt'
# attacker.vm.provision :salt do |salt|
# salt.minion_config = 'salt/minion'
# salt.run_highstate = true
# salt.verbose = true
# end
end
end

View File

@@ -0,0 +1,37 @@
#!/usr/bin/env python3
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: t -*-
# vi: set ft=python sts=4 ts=4 sw=4 noet :
# This file is part of Fail2Ban.
#
# Fail2Ban is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Fail2Ban is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Fail2Ban; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""
Fail2Ban reads log file that contains password failure report
and bans the corresponding IP addresses using firewall rules.
This tools starts/stops fail2ban server or does client/server communication,
to change/read parameters of the server or jails.
"""
__author__ = "Fail2Ban Developers"
__copyright__ = "Copyright (c) 2004-2008 Cyril Jaquier, 2012-2014 Yaroslav Halchenko, 2014-2016 Serg G. Brester"
__license__ = "GPL"
from fail2ban.client.fail2banclient import exec_command_line, sys
if __name__ == "__main__":
exec_command_line(sys.argv)

View File

@@ -0,0 +1,34 @@
#!/usr/bin/env python3
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: t -*-
# vi: set ft=python sts=4 ts=4 sw=4 noet :
#
# This file is part of Fail2Ban.
#
# Fail2Ban is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Fail2Ban is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Fail2Ban; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""
Fail2Ban reads log file that contains password failure report
and bans the corresponding IP addresses using firewall rules.
This tools can test regular expressions for "fail2ban".
"""
__author__ = "Fail2Ban Developers"
__copyright__ = "Copyright (c) 2004-2008 Cyril Jaquier, 2012-2014 Yaroslav Halchenko"
__license__ = "GPL"
from fail2ban.client.fail2banregex import exec_command_line
exec_command_line()

View File

@@ -0,0 +1,37 @@
#!/usr/bin/env python3
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: t -*-
# vi: set ft=python sts=4 ts=4 sw=4 noet :
# This file is part of Fail2Ban.
#
# Fail2Ban is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Fail2Ban is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Fail2Ban; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""
Fail2Ban reads log file that contains password failure report
and bans the corresponding IP addresses using firewall rules.
This tool starts/stops fail2ban server or does client/server communication
to change/read parameters of the server or jails.
"""
__author__ = "Fail2Ban Developers"
__copyright__ = "Copyright (c) 2004-2008 Cyril Jaquier, 2012-2014 Yaroslav Halchenko, 2014-2016 Serg G. Brester"
__license__ = "GPL"
from fail2ban.client.fail2banserver import exec_command_line, sys
if __name__ == "__main__":
exec_command_line(sys.argv)

View File

@@ -0,0 +1,71 @@
#!/usr/bin/env python3
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: t -*-
# vi: set ft=python sts=4 ts=4 sw=4 noet :
"""Script to run Fail2Ban tests battery
"""
# This file is part of Fail2Ban.
#
# Fail2Ban is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Fail2Ban is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Fail2Ban; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
__author__ = "Cyril Jaquier"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2012- Yaroslav Halchenko"
__license__ = "GPL"
import logging
import os
import sys
import time
import unittest
# Check if local fail2ban module exists, and use if it exists by
# modifying the path. This is done so that tests can be used in dev
# environment.
if os.path.exists("fail2ban/__init__.py"):
sys.path.insert(0, ".")
from fail2ban.version import version
from fail2ban.tests.utils import getOptParser, initProcess, gatherTests
from fail2ban.setup import updatePyExec
# Update fail2ban-python env to current python version (where f2b-modules located/installed)
bindir = os.path.dirname(
# __file__ seems to be overwritten sometimes on some python versions (e.g. bug of 2.6 by running under cProfile, etc.):
sys.argv[0] if os.path.basename(sys.argv[0]) == 'fail2ban-testcases' else __file__
)
updatePyExec(bindir)
(opts, regexps) = getOptParser(__doc__).parse_args()
#
# Process initialization corresponding options (logging, default options, etc.)
#
opts = initProcess(opts)
verbosity = opts.verbosity
#
# Gather tests (and filter corresponding options)
#
tests = gatherTests(regexps, opts)
#
# Run the tests
#
testRunner = unittest.TextTestRunner(verbosity=verbosity)
tests_results = testRunner.run(tests)
if not tests_results.wasSuccessful(): # pragma: no cover
sys.exit(1)

View File

@@ -0,0 +1,104 @@
# Fail2ban configuration file
#
# Action to report IP address to abuseipdb.com
# You must sign up to obtain an API key from abuseipdb.com.
#
# NOTE: These reports may include sensitive Info.
# If you want cleaner reports that ensure no user data see the helper script at the below website.
#
# IMPORTANT:
#
# Reporting an IP of abuse is a serious complaint. Make sure that it is
# serious. Fail2ban developers and network owners recommend you only use this
# action for:
# * The recidive where the IP has been banned multiple times
# * Where maxretry has been set quite high, beyond the normal user typing
# password incorrectly.
# * For filters that have a low likelihood of receiving human errors
#
# This action relies on a api_key being added to the above action conf,
# and the appropriate categories set.
#
# Example, for ssh bruteforce (in section [sshd] of `jail.local`):
# action = %(known/action)s
# abuseipdb[abuseipdb_apikey="my-api-key", abuseipdb_category="18,22"]
#
# See below for categories.
#
# Added to fail2ban by Andrew James Collett (ajcollett)
## abuseIPDB Categories, `the abuseipdb_category` MUST be set in the jail.conf action call.
# Example, for ssh bruteforce: action = %(action_abuseipdb)s[abuseipdb_category="18,22"]
# ID Title Description
# 3 Fraud Orders
# 4 DDoS Attack
# 9 Open Proxy
# 10 Web Spam
# 11 Email Spam
# 14 Port Scan
# 18 Brute-Force
# 19 Bad Web Bot
# 20 Exploited Host
# 21 Web App Attack
# 22 SSH Secure Shell (SSH) abuse. Use this category in combination with more specific categories.
# 23 IoT Targeted
# See https://abuseipdb.com/categories for more descriptions
[Definition]
# bypass action for restored tickets
norestored = 1
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart =
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop =
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
#
# ** IMPORTANT! **
#
# By default, this posts directly to AbuseIPDB's API, unfortunately
# this results in a lot of backslashes/escapes appearing in the
# reports. This also may include info like your hostname.
# If you have your own web server with PHP available, you can
# use my (Shaun's) helper PHP script by commenting out the first #actionban
# line below, uncommenting the second one, and pointing the URL at
# wherever you install the helper script. For the PHP helper script, see
# <https://github.com/parseword/fail2ban-abuseipdb/>
#
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = lgm=$(printf '%%.1000s\n...' "<matches>"); curl -sSf "https://api.abuseipdb.com/api/v2/report" -H "Accept: application/json" -H "Key: <abuseipdb_apikey>" --data-urlencode "comment=$lgm" --data-urlencode "ip=<ip>" --data "categories=<abuseipdb_category>"
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban =
[Init]
# Option: abuseipdb_apikey
# Notes Your API key from abuseipdb.com
# Values: STRING Default: None
# Register for abuseipdb [https://www.abuseipdb.com], get api key and set below.
# You will need to set the category in the action call.
abuseipdb_apikey =

View File

@@ -0,0 +1,25 @@
# Fail2Ban configuration file
# https://www.rfxn.com/projects/advanced-policy-firewall/
#
# Note: APF doesn't play nicely with other actions. It has been observed to
# remove bans created by other iptables based actions. If you are going to use
# this action, use it for all of your jails.
#
# DON'T MIX APF and other IPTABLES based actions
[Definition]
actionstart =
actionstop =
actioncheck =
actionban = apf --deny <ip> "banned by Fail2Ban <name>"
actionunban = apf --remove <ip>
[Init]
# Name used in APF configuration
#
name = default
# DEV NOTES:
#
# Author: Mark McKinstry

View File

@@ -0,0 +1,107 @@
# Fail2Ban configuration file
#
# Author: Chris Caron <lead2gold@gmail.com>
#
# ban & send a notification to one or more of the 120+ services supported by
# Apprise.
# - See https://appriseit.com/services/ for details on what is supported.
# - See https://appriseit.com/getting-started/configuration/ for information
# on how to prepare an Apprise configuration file.
#
# This plugin requires that Apprise is installed on your system:
#
# pip install apprise
#
# Breakdown:
# config provide a path to an Apprise Config file
# The default is /etc/fail2ban/apprise.conf if not provided.
# Both YAML and TEXT formats are supported.
# You can even point your configuration to an Apprise API
# endpoint.
#
# args Provide additional arguments to support the Apprise CLI.
# See https://appriseit.com/cli/usage/ for additional options.
# the --tag (-g) is incredibly useful for integrating with
# fail2ban as you can exclusively have it target specific
# notifications this way.
#
# Config Example #1: Simple
# 1. Create a /etc/fail2ban/apprise.conf
# ```
# # /etc/fail2ban/apprise.conf
# fail2ban=mailto://user:pass@example.com
# ```
# 2 In jail:
# ```
# action = %(action_)s
# apprise[args='--tag fail2ban']
# ```
#
# Config Example #2: YAML an Custom path
# 1. Create a /etc/fail2ban/apprise.conf
# ```
# # /etc/fail2ban/apprise.yaml
# urls:
# - mailto://user:pass@example.com:
# tags: f2b
# ```
# 2. In jail:
# ```
# action = %(action_)s
# apprise[config='/etc/fail2ban/apprise.yaml',args='--tag f2b']
# ```
#
# Config Example #3: Apprise API
# 1. In jail:
# ```
# action = %(action_)s
# apprise[config='http://apprise.example.ca/get/mykey',args='-g f2b']
# ```
[Definition]
# Option: actionstart
# Notes.: command executed once at the start of Fail2Ban.
# Values: CMD
#
actionstart = printf %%b "The jail <name> has been started successfully." | <apprise> -t "[Fail2Ban] <name>: started on `uname -n`"
# Option: actionstop
# Notes.: command executed once at the end of Fail2Ban
# Values: CMD
#
actionstop = printf %%b "The jail <name> has been stopped." | <apprise> -t "[Fail2Ban] <name>: stopped on `uname -n`"
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = printf %%b "The IP <ip> has just been banned by Fail2Ban after <failures> attempts against <name>" | <apprise> -n "warning" -t "[Fail2Ban] <name>: banned <ip> from `uname -n`"
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban =
[Init]
# Define location of the default apprise configuration file to use
#
config = /etc/fail2ban/apprise.conf
# Support passing in arguments for example: "-g fail2ban"
#
args =
#
apprise = apprise -c "<config>" <args>

View File

@@ -0,0 +1,87 @@
# Fail2Ban configuration file
#
# Author: Steven Hiscocks
#
#
# Action to report IP address to blocklist.de
# Blocklist.de must be signed up to at www.blocklist.de
# Once registered, one or more servers can be added.
# This action requires the server 'email address' and the associated apikey.
#
# From blocklist.de:
# www.blocklist.de is a free and voluntary service provided by a
# Fraud/Abuse-specialist, whose servers are often attacked on SSH-,
# Mail-Login-, FTP-, Webserver- and other services.
# The mission is to report all attacks to the abuse departments of the
# infected PCs/servers to ensure that the responsible provider can inform
# the customer about the infection and disable them
#
# IMPORTANT:
#
# Reporting an IP of abuse is a serious complaint. Make sure that it is
# serious. Fail2ban developers and network owners recommend you only use this
# action for:
# * The recidive where the IP has been banned multiple times
# * Where maxretry has been set quite high, beyond the normal user typing
# password incorrectly.
# * For filters that have a low likelihood of receiving human errors
#
[Definition]
# bypass reporting of restored (already reported) tickets:
norestored = 1
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart =
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop =
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = curl --fail --data-urlencode "server=<email>" --data "apikey=<apikey>" --data "service=<service>" --data "ip=<ip>" --data-urlencode "logs=<matches><br>" --data 'format=text' --user-agent "<agent>" "https://www.blocklist.de/en/httpreports.html"
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban =
# Option: email
# Notes server email address, as per blocklist.de account
# Values: STRING Default: None
#
#email =
# Option: apikey
# Notes your user blocklist.de user account apikey
# Values: STRING Default: None
#
#apikey =
# Option: service
# Notes service name you are reporting on, typically aligns with filter name
# see http://www.blocklist.de/en/httpreports.html for full list
# Values: STRING Default: None
#
#service =

View File

@@ -0,0 +1,94 @@
# Fail2Ban configuration file
#
# Author: Nick Munger
# Modified by: Ken Menzel
# Daniel Black (start/stop)
# Fabian Wenk (many ideas as per fail2ban users list)
#
# Ensure firewall_enable="YES" in the top of /etc/rc.conf
#
[Definition]
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart = ipfw show | fgrep -c -m 1 -s 'table(<table>)' > /dev/null 2>&1 || (
num=$(ipfw show | awk 'BEGIN { b = <lowest_rule_num> } { if ($1 == b) { b = $1 + 1 } } END { print b }');
ipfw -q add "$num" <blocktype> <block> from table\(<table>\) to me <port>; echo "$num" > "<startstatefile>"
)
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop = [ ! -f <startstatefile> ] || ( read num < "<startstatefile>" <br> ipfw -q delete $num <br> rm "<startstatefile>" )
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
# requires an ipfw rule like "deny ip from table(1) to me"
actionban = e=`ipfw table <table> add <ip> 2>&1`; x=$?; [ $x -eq 0 -o "$e" = 'ipfw: setsockopt(IP_FW_TABLE_XADD): File exists' ] || echo "$e" | grep -q "record already exists" || { echo "$e" 1>&2; exit $x; }
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban = e=`ipfw table <table> delete <ip> 2>&1`; x=$?; [ $x -eq 0 -o "$e" = 'ipfw: setsockopt(IP_FW_TABLE_XDEL): No such process' ] || echo "$e" | grep -q "record not found" || { echo "$e" 1>&2; exit $x; }
[Init]
# Option: table
# Notes: The ipfw table to use. If a ipfw rule using this table already exists,
# this action will not create a ipfw rule to block it and the following
# options will have no effect.
# Values: NUM
table = 1
# Option: port
# Notes.: Specifies port to monitor. Blank indicate block all ports.
# Values: [ NUM | STRING ]
#
port =
# Option: startstatefile
# Notes: A file to indicate that the table rule that was added. Ensure it is unique per table.
# Values: STRING
startstatefile = /var/run/fail2ban/ipfw-started-table_<table>
# Option: block
# Notes: This is how much to block.
# Can be "ip", "tcp", "udp" or various other options.
# Values: STRING
block = ip
# Option: blocktype
# Notes.: How to block the traffic. Use a action from man 5 ipfw
# Common values: deny, unreach port, reset
# ACTION definition at the top of man ipfw for allowed values.
# Values: STRING
#
blocktype = unreach port
# Option: lowest_rule_num
# Notes: When fail2ban starts with action and there is no rule for the given table yet
# then fail2ban will start looking for an empty slot starting with this rule number.
# Values: NUM
lowest_rule_num = 111

View File

@@ -0,0 +1,93 @@
#
# Author: Logic-32
#
# IMPORTANT
#
# Please set jail.local's permission to 640 because it contains your CF API token.
#
# This action depends on curl.
#
# To get your Cloudflare API token: https://developers.cloudflare.com/api/tokens/create/
#
# Cloudflare Firewall API: https://developers.cloudflare.com/firewall/api/cf-firewall-rules/endpoints/
[Definition]
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart =
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop =
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: <ip> IP address
# <failures> number of failures
# <time> unix timestamp of the ban time
# Values: CMD
actionban = curl -s -X POST "<_cf_api_url>" \
<_cf_api_prms> \
--data '{"mode":"<cfmode>","configuration":{"target":"<cftarget>","value":"<ip>"},"notes":"<notes>"}'
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: <ip> IP address
# <failures> number of failures
# <time> unix timestamp of the ban time
# Values: CMD
#
actionunban = id=$(curl -s -G -X GET "<_cf_api_url>" \
--data-urlencode "mode=<cfmode>" --data-urlencode "notes=<notes>" --data-urlencode "configuration.target=<cftarget>" --data-urlencode "configuration.value=<ip>" \
<_cf_api_prms> \
| awk -F"[,:}]" '{for(i=1;i<=NF;i++){if($i~/'id'\042/){print $(i+1)}}}' \
| tr -d ' "' \
| head -n 1)
if [ -z "$id" ]; then echo "<name>: id for <ip> cannot be found using target <cftarget>"; exit 0; fi; \
curl -s -X DELETE "<_cf_api_url>/$id" \
<_cf_api_prms> \
--data '{"cascade": "none"}'
_cf_api_url = https://api.cloudflare.com/client/v4/zones/<cfzone>/firewall/access_rules/rules
_cf_api_prms = -H "Authorization: Bearer <cftoken>" -H "Content-Type: application/json"
[Init]
# Declare your Cloudflare Authorization Bearer Token in the [DEFAULT] section of your jail.local file.
# The Cloudflare <ZONE_ID> of the domain you want to manage.
#
# cfzone =
# Your personal Cloudflare token. Ideally restricted to just have "Zone.Firewall Services" permissions.
#
# cftoken =
# Target of the firewall rule. Default is "ip" (v4).
#
cftarget = ip
# The firewall mode Cloudflare should use. Default is "block" (deny access).
# Consider also "js_challenge" or other "allowed_modes" if you want.
#
cfmode = block
# The message to include in the firewall IP banning rule.
#
notes = Fail2Ban <name>
[Init?family=inet6]
cftarget = ip6

View File

@@ -0,0 +1,88 @@
#
# Author: Mike Rushton
#
# IMPORTANT
#
# Please set jail.local's permission to 640 because it contains your CF API key.
#
# This action depends on curl (and optionally jq).
# Referenced from http://www.normyee.net/blog/2012/02/02/adding-cloudflare-support-to-fail2ban by NORM YEE
#
# To get your CloudFlare API Key: https://www.cloudflare.com/a/account/my-account
#
# CloudFlare API error codes: https://www.cloudflare.com/docs/host-api.html#s4.2
[Definition]
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart =
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop =
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: <ip> IP address
# <failures> number of failures
# <time> unix timestamp of the ban time
# Values: CMD
#
# API v1
#actionban = curl -s -o /dev/null https://www.cloudflare.com/api_json.html -d 'a=ban' -d 'tkn=<cftoken>' -d 'email=<cfuser>' -d 'key=<ip>'
# API v4
actionban = curl -s -o /dev/null -X POST <_cf_api_prms> \
-d '{"mode":"block","configuration":{"target":"<cftarget>","value":"<ip>"},"notes":"Fail2Ban <name>"}' \
<_cf_api_url>
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: <ip> IP address
# <failures> number of failures
# <time> unix timestamp of the ban time
# Values: CMD
#
# API v1
#actionunban = curl -s -o /dev/null https://www.cloudflare.com/api_json.html -d 'a=nul' -d 'tkn=<cftoken>' -d 'email=<cfuser>' -d 'key=<ip>'
# API v4
actionunban = id=$(curl -s -X GET <_cf_api_prms> \
"<_cf_api_url>?mode=block&configuration_target=<cftarget>&configuration_value=<ip>&page=1&per_page=1&notes=Fail2Ban%%20<name>" \
| { jq -r '.result[0].id' 2>/dev/null || tr -d '\n' | sed -nE 's/^.*"result"\s*:\s*\[\s*\{\s*"id"\s*:\s*"([^"]+)".*$/\1/p'; })
if [ -z "$id" ]; then echo "<name>: id for <ip> cannot be found"; exit 0; fi;
curl -s -o /dev/null -X DELETE <_cf_api_prms> "<_cf_api_url>/$id"
_cf_api_url = https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules
_cf_api_prms = -H 'X-Auth-Email: <cfuser>' -H 'X-Auth-Key: <cftoken>' -H 'Content-Type: application/json'
[Init]
# If you like to use this action with mailing whois lines, you could use the composite action
# action_cf_mwl predefined in jail.conf, just define in your jail:
#
# action = %(action_cf_mwl)s
# # Your CF account e-mail
# cfemail =
# # Your CF API Key
# cfapikey =
cftoken =
cfuser =
cftarget = ip
[Init?family=inet6]
cftarget = ip6

View File

@@ -0,0 +1,121 @@
# Fail2Ban configuration file
#
# Author: Russell Odom <russ@gloomytrousers.co.uk>, Daniel Black
# Sends a complaint e-mail to addresses listed in the whois record for an
# offending IP address.
# This uses the https://abusix.com/contactdb.html to lookup abuse contacts.
#
# DEPENDENCIES:
# This requires the dig command from bind-utils
#
# You should provide the <logpath> in the jail config - lines from the log
# matching the given IP address will be provided in the complaint as evidence.
#
# WARNING
# -------
#
# Please do not use this action unless you are certain that fail2ban
# does not result in "false positives" for your deployment. False
# positive reports could serve a misfavor to the original cause by
# flooding corresponding contact addresses, and complicating the work
# of administration personnel responsible for handling (verified) legit
# complains.
#
# Please consider using e.g. sendmail-whois-lines.conf action which
# would send the reports with relevant information to you, so the
# report could be first reviewed and then forwarded to a corresponding
# contact if legit.
#
[INCLUDES]
before = helpers-common.conf
[Definition]
# Used in test cases for coverage internal transformations
debug = 0
# bypass ban/unban for restored tickets
norestored = 1
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart =
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop =
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = oifs=${IFS};
RESOLVER_ADDR="%(addr_resolver)s"
if [ "<debug>" -gt 0 ]; then echo "try to resolve $RESOLVER_ADDR"; fi
ADDRESSES=$(dig +short -t txt -q $RESOLVER_ADDR | tr -d '"')
IFS=,; ADDRESSES=$(echo $ADDRESSES)
IFS=${oifs}
IP=<ip>
if [ ! -z "$ADDRESSES" ]; then
( printf %%b "<message>\n"; date '+Note: Local timezone is %%z (%%Z)';
printf %%b "\nLines containing failures of <ip> (max <grepmax>)\n";
%(_grep_logs)s;
) | <mailcmd> "Abuse from <ip>" <mailargs> $ADDRESSES
fi
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban =
# Server as resolver used in dig command
#
addr_resolver = <ip-rev>abuse-contacts.abusix.org
# Default message used for abuse content
#
message = Dear Sir/Madam,\n\nWe have detected abuse from the IP address $IP, which according to a abusix.com is on your network. We would appreciate if you would investigate and take action as appropriate.\n\nLog lines are given below, but please ask if you require any further information.\n\n(If you are not the correct person to contact about this please accept our apologies - your e-mail address was extracted from the whois record by an automated process.)\n\n This mail was generated by Fail2Ban.\nThe recipient address of this report was provided by the Abuse Contact DB by abusix.com. abusix.com does not maintain the content of the database. All information which we pass out, derives from the RIR databases and is processed for ease of use. If you want to change or report non working abuse contacts please contact the appropriate RIR. If you have any further question, contact abusix.com directly via email (info@abusix.com). Information about the Abuse Contact Database can be found here: https://abusix.com/global-reporting/abuse-contact-db\nabusix.com is neither responsible nor liable for the content or accuracy of this message.\n
# Path to the log files which contain relevant lines for the abuser IP
#
logpath = /dev/null
# Option: mailcmd
# Notes.: Your system mail command. Is passed 2 args: subject and recipient
# Values: CMD
#
mailcmd = mail -E 'set escape' -s
# Option: mailargs
# Notes.: Additional arguments to mail command. e.g. for standard Unix mail:
# CC reports to another address:
# -c me@example.com
# Appear to come from a different address - the '--' indicates
# arguments to be passed to Sendmail:
# -- -f me@example.com
# Values: [ STRING ]
#
mailargs =
# Number of log lines to include in the email
#
#grepmax = 1000
#grepopts = -m <grepmax>

View File

@@ -0,0 +1,26 @@
# Fail2Ban configuration file
# http://configserver.com/cp/csf.html
#
# Note: CSF doesn't play nicely with other actions. It has been observed to
# remove bans created by other iptables based actions. If you are going to use
# this action, use it for all of your jails.
#
# DON'T MIX CSF and other IPTABLES based actions
[Definition]
actionstart =
actionstop =
actioncheck =
actionban = csf --deny <ip> "banned by Fail2Ban <name>"
actionunban = csf --denyrm <ip>
[Init]
# Name used in CSF configuration
#
name = default
# DEV NOTES:
#
# based on apf.conf by Mark McKinstry

View File

@@ -0,0 +1,207 @@
# Fail2Ban configuration file
#
# Author: Russell Odom <russ@gloomytrousers.co.uk>
# Submits attack reports to DShield (http://www.dshield.org/)
#
# You MUST configure at least:
# <port> (the port that's being attacked - use number not name).
#
# You SHOULD also provide:
# <myip> (your public IP address, if it's not the address of eth0)
# <userid> (your DShield userID, if you have one - recommended, but reports will
# be used anonymously if not)
# <protocol> (the protocol in use - defaults to tcp)
#
# Best practice is to provide <port> and <protocol> in jail.conf like this:
# action = dshield[port=1234,protocol=tcp]
#
# ...and create "dshield.local" with contents something like this:
# [Init]
# myip = 10.0.0.1
# userid = 12345
#
# Other useful configuration values are <mailargs> (you can use for specifying
# a different sender address for the report e-mails, which should match what is
# configured at DShield), and <lines>/<minreportinterval>/<maxbufferage> (to
# configure how often the buffer is flushed).
#
[Definition]
# bypass ban/unban for restored tickets
norestored = 1
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart =
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop = if [ -f <tmpfile>.buffer ]; then
cat <tmpfile>.buffer | <mailcmd> "FORMAT DSHIELD USERID <userid> TZ `date +%%z | sed 's/\([+-]..\)\(..\)/\1:\2/'` Fail2Ban" <mailargs> <dest>
date +%%s > <tmpfile>.lastsent
fi
rm -f <tmpfile>.buffer <tmpfile>.first
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
# See http://www.dshield.org/specs.html for more on report format/notes
#
# Note: We are currently using <time> for the timestamp because no tag is
# available to indicate the timestamp of the log message(s) which triggered the
# ban. Therefore the timestamps we are using in the report, whilst often only a
# few seconds out, are incorrect. See
# http://sourceforge.net/tracker/index.php?func=detail&aid=2017795&group_id=121032&atid=689047
#
actionban = TZONE=`date +%%z | sed 's/\([+-]..\)\(..\)/\1:\2/'`
DATETIME="`perl -e '@t=localtime(<time>);printf "%%4d-%%02d-%%02d %%02d:%%02d:%%02d",1900+$t[5],$t[4]+1,$t[3],$t[2],$t[1],$t[0]'` $TZONE"
PROTOCOL=`awk '{IGNORECASE=1;if($1=="<protocol>"){print $2;exit}}' /etc/protocols`
if [ -z "$PROTOCOL" ]; then PROTOCOL=<protocol>; fi
printf %%b "$DATETIME\t<userid>\t<failures>\t<ip>\t<srcport>\t<myip>\t<port>\t$PROTOCOL\t<tcpflags>\n" >> <tmpfile>.buffer
NOW=`date +%%s`
if [ ! -f <tmpfile>.first ]; then
echo <time> | cut -d. -f1 > <tmpfile>.first
fi
if [ ! -f <tmpfile>.lastsent ]; then
echo 0 > <tmpfile>.lastsent
fi
LOGAGE=$(($NOW - `cat <tmpfile>.first`))
LASTREPORT=$(($NOW - `cat <tmpfile>.lastsent`))
LINES=$( wc -l <tmpfile>.buffer | awk '{ print $1 }' )
if [ $LINES -ge <lines> && $LASTREPORT -gt <minreportinterval> ] || [ $LOGAGE -gt <maxbufferage> ]; then
cat <tmpfile>.buffer | <mailcmd> "FORMAT DSHIELD USERID <userid> TZ $TZONE Fail2Ban" <mailargs> <dest>
rm -f <tmpfile>.buffer <tmpfile>.first
echo $NOW > <tmpfile>.lastsent
fi
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban = if [ -f <tmpfile>.first ]; then
NOW=`date +%%s`
LOGAGE=$(($NOW - `cat <tmpfile>.first`))
if [ $LOGAGE -gt <maxbufferage> ]; then
cat <tmpfile>.buffer | <mailcmd> "FORMAT DSHIELD USERID <userid> TZ `date +%%z | sed 's/\([+-]..\)\(..\)/\1:\2/'` Fail2Ban" <mailargs> <dest>
rm -f <tmpfile>.buffer <tmpfile>.first
echo $NOW > <tmpfile>.lastsent
fi
fi
[Init]
# Option: port
# Notes.: The target port for the attack (numerical). MUST be provided in the
# jail config, as it cannot be detected here.
# Values: [ NUM ]
#
port = ???
# Option: userid
# Notes.: Your DShield user ID. Should be provided either in the jail config or
# in a .local file.
# Register at https://secure.dshield.org/register.html
# Values: [ NUM ]
#
userid = 0
# Option: myip
# Notes.: The target IP for the attack (your public IP). Should be provided
# either in the jail config or in a .local file unless your PUBLIC IP
# is the first IP assigned to eth0
# Values: [ an IP address ] Default: Tries to find the IP address of eth0,
# which in most cases will be a private IP, and therefore incorrect
#
myip = `ip -4 addr show dev eth0 | grep inet | head -n 1 | sed -r 's/.*inet ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*/\1/'`
# Option: protocol
# Notes.: The protocol over which the attack is happening
# Values: [ tcp | udp | icmp | (any other protocol name from /etc/protocols) | NUM ] Default: tcp
#
protocol = tcp
# Option: lines
# Notes.: How many lines to buffer before making a report. Regardless of this,
# reports are sent a minimum of <minreportinterval> apart, or if the
# buffer contains an event over <maxbufferage> old, or on shutdown
# Values: [ NUM ]
#
lines = 50
# Option: minreportinterval
# Notes.: Minimum period (in seconds) that must elapse before we submit another
# batch of reports. DShield request a minimum of 1 hour (3600 secs)
# between reports.
# Values: [ NUM ]
#
minreportinterval = 3600
# Option: maxbufferage
# Notes.: Maximum age (in seconds) of the oldest report in the buffer before we
# submit the batch, even if we haven't reached <lines> yet. Note that
# this is only checked on each ban/unban, and that we always send
# anything in the buffer on shutdown. Must be greater than
# Values: [ NUM ]
#
maxbufferage = 21600
# Option: srcport
# Notes.: The source port of the attack. You're unlikely to have this info, so
# you can leave the default
# Values: [ NUM ]
#
srcport = ???
# Option: tcpflags
# Notes.: TCP flags on attack. You're unlikely to have this info, so you can
# leave empty
# Values: [ STRING ]
#
tcpflags =
# Option: mailcmd
# Notes.: Your system mail command. Is passed 2 args: subject and recipient
# Values: CMD
#
mailcmd = mail -E 'set escape' -s
# Option: mailargs
# Notes.: Additional arguments to mail command. e.g. for standard Unix mail:
# CC reports to another address:
# -c me@example.com
# Appear to come from a different address (the From address must match
# the one configured at DShield - the '--' indicates arguments to be
# passed to Sendmail):
# -- -f me@example.com
# Values: [ STRING ]
#
mailargs =
# Option: dest
# Notes.: Destination e-mail address for reports
# Values: [ STRING ]
#
dest = reports@dshield.org
# Option: tmpfile
# Notes.: Base name of temporary files used for buffering
# Values: [ STRING ]
#
tmpfile = /var/run/fail2ban/tmp-dshield

View File

@@ -0,0 +1,63 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
#
[Definition]
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart = if [ ! -z '<target>' ]; then touch <target>; fi;
printf %%b "<init>\n" <to_target>
echo "%(debug)s started"
# Option: actionflush
# Notes.: command executed once to flush (clear) all IPS, by shutdown (resp. by stop of the jail or this action)
# Values: CMD
#
actionflush = printf %%b "-*\n" <to_target>
echo "%(debug)s clear all"
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop = if [ ! -z '<target>' ]; then rm -f <target>; fi;
echo "%(debug)s stopped"
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = printf %%b "+<ip>\n" <to_target>
echo "%(debug)s banned <ip> (family: <family>)"
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban = printf %%b "-<ip>\n" <to_target>
echo "%(debug)s unbanned <ip> (family: <family>)"
debug = [<name>] <actname> <target> --
[Init]
init = 123
target = /var/run/fail2ban/fail2ban.dummy
to_target = >> <target>

View File

@@ -0,0 +1,45 @@
# Fail2Ban configuration file
#
# Author: Donald Yandt
# Because of the --remove-rules in stop this action requires firewalld-0.3.8+
[INCLUDES]
before = firewallcmd-common.conf
[Definition]
actionstart = firewall-cmd --direct --add-chain <family> filter f2b-<name>
firewall-cmd --direct --add-rule <family> filter f2b-<name> 1000 -j RETURN
firewall-cmd --direct --add-rule <family> filter <chain> 0 -j f2b-<name>
actionstop = firewall-cmd --direct --remove-rule <family> filter <chain> 0 -j f2b-<name>
firewall-cmd --direct --remove-rules <family> filter f2b-<name>
firewall-cmd --direct --remove-chain <family> filter f2b-<name>
# Example actioncheck: firewall-cmd --direct --get-chains ipv4 filter | sed -e 's, ,\n,g' | grep -q '^f2b-recidive$'
actioncheck = firewall-cmd --direct --get-chains <family> filter | sed -e 's, ,\n,g' | grep -q '^f2b-<name>$'
actionban = firewall-cmd --direct --add-rule <family> filter f2b-<name> 0 -s <ip> -j <blocktype>
actionunban = firewall-cmd --direct --remove-rule <family> filter f2b-<name> 0 -s <ip> -j <blocktype>
# DEV NOTES:
#
# Author: Donald Yandt
# Uses "FirewallD" instead of the "iptables daemon".
#
#
# Output:
# actionstart:
# $ firewall-cmd --direct --add-chain ipv4 filter f2b-recidive
# success
# $ firewall-cmd --direct --add-rule ipv4 filter f2b-recidive 1000 -j RETURN
# success
# $ sudo firewall-cmd --direct --add-rule ipv4 filter INPUT_direct 0 -j f2b-recidive
# success

View File

@@ -0,0 +1,76 @@
# Fail2Ban configuration file
#
# Author: Donald Yandt
#
[Init]
# Option: name
# Notes Default name of the chain
# Values: STRING
name = default
# Option port
# Notes Can also use port numbers separated by a comma and in rich-rules comma and/or space.
# Value STRING Default: 1:65535
port = 1:65535
# Option: protocol
# Notes [ tcp | udp | icmp | all ]
# Values: STRING Default: tcp
protocol = tcp
# Option: family(ipv4)
# Notes specifies the socket address family type
# Values: STRING
family = ipv4
# Option: chain
# Notes specifies the firewalld chain to which the Fail2Ban rules should be
# added
# Values: STRING Default: INPUT_direct
chain = INPUT_direct
# Option: zone
# Notes use command firewall-cmd --get-active-zones to see a list of all active zones. See firewalld man pages for more information on zones
# Values: STRING Default: public
zone = public
# Option: service
# Notes use command firewall-cmd --get-services to see a list of services available
# Examples services: amanda-client amanda-k5-client bacula bacula-client dhcp dhcpv6 dhcpv6-client dns freeipa-ldap freeipa-ldaps
# freeipa-replication ftp high-availability http https imaps ipp ipp-client ipsec iscsi-target kadmin kerberos
# kpasswd ldap ldaps libvirt libvirt-tls mdns mosh mountd ms-wbt mysql nfs ntp openvpn pmcd pmproxy pmwebapi pmwebapis pop3s
# postgresql privoxy proxy-dhcp puppetmaster radius rpc-bind rsyncd samba samba-client sane smtp squid ssh synergy
# telnet tftp tftp-client tinc tor-socks transmission-client vdsm vnc-server wbem-https xmpp-bosh xmpp-client xmpp-local xmpp-server
# Values: STRING Default: ssh
service = ssh
# Option: rejecttype (ipv4)
# Notes See iptables/firewalld man pages for ipv4 reject types.
# Values: STRING
rejecttype = icmp-port-unreachable
# Option: blocktype (ipv4/ipv6)
# Notes See iptables/firewalld man pages for jump targets. Common values are REJECT,
# REJECT --reject-with icmp-port-unreachable, DROP
# Values: STRING
blocktype = REJECT --reject-with <rejecttype>
# Option: rich-blocktype (ipv4/ipv6)
# Notes See firewalld man pages for jump targets. Common values are reject,
# reject type="icmp-port-unreachable", drop
# Values: STRING
rich-blocktype = reject type='<rejecttype>'
[Init?family=inet6]
# Option: family(ipv6)
# Notes specifies the socket address family type
# Values: STRING
family = ipv6
# Option: rejecttype (ipv6)
# Note: See iptables/firewalld man pages for ipv6 reject types.
# Values: STRING
rejecttype = icmp6-port-unreachable

View File

@@ -0,0 +1,132 @@
# Fail2Ban action file for firewall-cmd/ipset
#
# This requires:
# ipset (package: ipset)
# firewall-cmd (package: firewalld)
#
# This is for ipset protocol 6 (and hopefully later) (ipset v6.14).
# Use ipset -V to see the protocol and version.
#
# IPset was a feature introduced in the linux kernel 2.6.39 and 3.0.0 kernels.
#
# If you are running on an older kernel you make need to patch in external
# modules.
[INCLUDES]
before = firewallcmd-common.conf
[Definition]
actionstart = <ipsbackend_<ipsetbackend>/actionstart>
firewall-cmd --direct --add-rule <family> filter <chain> 0 <actiontype> -m set --match-set <ipmset> src -j <blocktype>
actionflush = <ipsbackend_<ipsetbackend>/actionflush>
actionstop = firewall-cmd --direct --remove-rule <family> filter <chain> 0 <actiontype> -m set --match-set <ipmset> src -j <blocktype>
<actionflush>
<ipsbackend_<ipsetbackend>/actionstop>
actionban = <ipsbackend_<ipsetbackend>/actionban>
# actionprolong = %(actionban)s
actionunban = <ipsbackend_<ipsetbackend>/actionunban>
[ipsbackend_ipset]
actionstart = ipset -exist create <ipmset> <ipsettype> timeout <default-ipsettime> maxelem <maxelem> <familyopt>
actionflush = ipset flush <ipmset>
actionstop = ipset destroy <ipmset> 2>/dev/null || { sleep 1; ipset destroy <ipmset>; }
actionban = ipset -exist add <ipmset> <ip> timeout <ipsettime>
actionunban = ipset -exist del <ipmset> <ip>
[ipsbackend_firewalld]
actionstart = firewall-cmd --direct --new-ipset=<ipmset> --type=<ipsettype> --option=timeout=<default-ipsettime> --option=maxelem=<maxelem> <firewalld_familyopt>
# TODO: there doesn't seem to be an explicit way to invoke the ipset flush function using firewall-cmd
actionflush =
actionstop = firewall-cmd --direct --delete-ipset=<ipmset>
actionban = firewall-cmd --ipset=<ipmset> --add-entry=<ip>
actionunban = firewall-cmd --ipset=<ipmset> --remove-entry=<ip>
[Init]
# Option: ipsettype
# Notes: specifies type of set, see `man --pager='less -p "^SET TYPES"' ipset` for details
# Values: hash:ip, hash:net, etc... Default: hash:ip
ipsettype = hash:ip
# Option: chain
# Notes specifies the iptables chain to which the fail2ban rules should be
# added
# Values: [ STRING ]
#
chain = INPUT_direct
# Option: default-ipsettime
# Notes: specifies default timeout in seconds (handled default ipset timeout only)
# Values: [ NUM ] Default: 0 (no timeout, managed by fail2ban by unban)
default-ipsettime = 0
# Option: ipsettime
# Notes: specifies ticket timeout (handled ipset timeout only)
# Values: [ NUM ] Default: 0 (managed by fail2ban by unban)
ipsettime = 0
# Option: maxelem
# Notes: maximal number of elements which can be stored in the ipset
# You may want to increase this for long-duration/high-volume jails
# Values: [ NUM ] Default: 65536
maxelem = 65536
# expression to calculate timeout from bantime, example:
# banaction = %(known/banaction)s[ipsettime='<timeout-bantime>']
timeout-bantime = $([ "<bantime>" -le 2147483 ] && echo "<bantime>" || echo 0)
# Option: ipsetbackend
# Notes.: defines the backend of ipset used for match-set (firewalld or ipset)
# Values: firewalld or ipset
# Default: ipset
ipsetbackend = ipset
# Option: actiontype
# Notes.: defines additions to the blocking rule
# Values: leave empty to block all attempts from the host
# Default: Value of the multiport
actiontype = <multiport>
# Option: allports
# Notes.: default addition to block all ports
# Usage.: use in jail config: banaction = firewallcmd-ipset[actiontype=<allports>]
# for all protocols: banaction = firewallcmd-ipset[actiontype=""]
allports = -p <protocol>
# Option: multiport
# Notes.: addition to block access only to specific ports
# Usage.: use in jail config: banaction = firewallcmd-ipset[actiontype=<multiport>]
multiport = -p <protocol> -m multiport --dports <port>
ipmset = f2b-<name>
familyopt =
firewalld_familyopt =
[Init?family=inet6]
ipmset = f2b-<name>6
familyopt = family inet6
firewalld_familyopt = --option=family=inet6
# DEV NOTES:
#
# Author: Edgar Hoch, Daniel Black, Sergey Brester and Mihail Politaev
# firewallcmd-new / iptables-ipset-proto6 combined for maximum goodness

View File

@@ -0,0 +1,26 @@
# Fail2Ban configuration file
#
# Author: Donald Yandt
# Because of the --remove-rules in stop this action requires firewalld-0.3.8+
[INCLUDES]
before = firewallcmd-common.conf
[Definition]
actionstart = firewall-cmd --direct --add-chain <family> filter f2b-<name>
firewall-cmd --direct --add-rule <family> filter f2b-<name> 1000 -j RETURN
firewall-cmd --direct --add-rule <family> filter <chain> 0 -m conntrack --ctstate NEW -p <protocol> -m multiport --dports <port> -j f2b-<name>
actionstop = firewall-cmd --direct --remove-rule <family> filter <chain> 0 -m conntrack --ctstate NEW -p <protocol> -m multiport --dports <port> -j f2b-<name>
firewall-cmd --direct --remove-rules <family> filter f2b-<name>
firewall-cmd --direct --remove-chain <family> filter f2b-<name>
# Example actioncheck: firewall-cmd --direct --get-chains ipv4 filter | sed -e 's, ,\n,g' | grep -q '^f2b-apache-modsecurity$'
actioncheck = firewall-cmd --direct --get-chains <family> filter | sed -e 's, ,\n,g' | grep -q '^f2b-<name>$'
actionban = firewall-cmd --direct --add-rule <family> filter f2b-<name> 0 -s <ip> -j <blocktype>
actionunban = firewall-cmd --direct --remove-rule <family> filter f2b-<name> 0 -s <ip> -j <blocktype>

View File

@@ -0,0 +1,47 @@
# Fail2Ban configuration file
#
# Because of the --remove-rules in stop this action requires firewalld-0.3.8+
[INCLUDES]
before = firewallcmd-common.conf
[Definition]
actionstart = firewall-cmd --direct --add-chain <family> filter f2b-<name>
firewall-cmd --direct --add-rule <family> filter f2b-<name> 1000 -j RETURN
firewall-cmd --direct --add-rule <family> filter <chain> 0 -m state --state NEW -p <protocol> -m multiport --dports <port> -j f2b-<name>
actionstop = firewall-cmd --direct --remove-rule <family> filter <chain> 0 -m state --state NEW -p <protocol> -m multiport --dports <port> -j f2b-<name>
firewall-cmd --direct --remove-rules <family> filter f2b-<name>
firewall-cmd --direct --remove-chain <family> filter f2b-<name>
actioncheck = firewall-cmd --direct --get-chains <family> filter | sed -e 's, ,\n,g' | grep -q 'f2b-<name>$'
actionban = firewall-cmd --direct --add-rule <family> filter f2b-<name> 0 -s <ip> -j <blocktype>
actionunban = firewall-cmd --direct --remove-rule <family> filter f2b-<name> 0 -s <ip> -j <blocktype>
# DEV NOTES:
#
# Author: Edgar Hoch
# Copied from iptables-new.conf and modified for use with firewalld by Edgar Hoch.
# It uses "firewall-cmd" instead of "iptables".
#
# Output:
#
# $ firewall-cmd --direct --add-chain ipv4 filter fail2ban-name
# success
# $ firewall-cmd --direct --add-rule ipv4 filter fail2ban-name 1000 -j RETURN
# success
# $ sudo firewall-cmd --direct --add-rule ipv4 filter INPUT_direct 0 -m state --state NEW -p tcp -m multiport --dports 22 -j fail2ban-name
# success
# $ firewall-cmd --direct --get-chains ipv4 filter
# fail2ban-name
# $ firewall-cmd --direct --get-chains ipv4 filter | od -h
# 0000000 6166 6c69 6232 6e61 6e2d 6d61 0a65
# $ firewall-cmd --direct --get-chains ipv4 filter | grep -Eq 'fail2ban-name( |$)' ; echo $?
# 0
# $ firewall-cmd -V
# 0.3.8

View File

@@ -0,0 +1,29 @@
# Fail2Ban configuration file
#
# Authors: Donald Yandt, Sergey G. Brester
#
# Because of the rich rule commands requires firewalld-0.3.1+
# This action uses firewalld rich-rules which gives you a cleaner iptables since it stores rules according to zones and not
# by chain. So for an example all deny rules will be listed under <zone>_deny and all log rules under <zone>_log.
#
# Also this action logs banned access attempts so you can filter that and increase ban time for offenders.
#
# If you use the --permanent rule you get a xml file in /etc/firewalld/zones/<zone>.xml that can be shared and parsed easliy
#
# This is an derivative of firewallcmd-rich-rules.conf, see there for details and other parameters.
[INCLUDES]
before = firewallcmd-rich-rules.conf
[Definition]
rich-suffix = log prefix='f2b-<name>' level='<level>' limit value='<rate>/m' <rich-blocktype>
[Init]
# log levels are "emerg", "alert", "crit", "error", "warning", "notice", "info" or "debug"
level = info
# log rate per minute
rate = 1

View File

@@ -0,0 +1,44 @@
# Fail2Ban configuration file
#
# Author: Donald Yandt
#
# Because of the rich rule commands requires firewalld-0.3.1+
# This action uses firewalld rich-rules which gives you a cleaner iptables since it stores rules according to zones and not
# by chain. So for an example all deny rules will be listed under <zone>_deny.
#
# If you use the --permanent rule you get a xml file in /etc/firewalld/zones/<zone>.xml that can be shared and parsed easliy
#
# Example commands to view rules:
# firewall-cmd [--zone=<zone>] --list-rich-rules
# firewall-cmd [--zone=<zone>] --list-all
# firewall-cmd [--zone=zone] --query-rich-rule='rule'
[INCLUDES]
before = firewallcmd-common.conf
[Definition]
actionstart =
actionstop =
actioncheck =
#you can also use zones and/or service names.
#
# zone example:
# firewall-cmd --zone=<zone> --add-rich-rule="rule family='ipv4' source address='<ip>' port port='<port>' protocol='<protocol>' <rich-blocktype>"
#
# service name example:
# firewall-cmd --zone=<zone> --add-rich-rule="rule family='ipv4' source address='<ip>' service name='<service>' <rich-blocktype>"
#
# Because rich rules can only handle single or a range of ports we must split ports and execute the command for each port. Ports can be single and ranges separated by a comma or space for an example: http, https, 22-60, 18 smtp
fwcmd_rich_rule = rule family=\"<family>\" source address=\"<ip>\" port port=\"$p\" protocol=\"<protocol>\" %(rich-suffix)s
actionban = ports="<port>"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --add-rich-rule="%(fwcmd_rich_rule)s"; done
actionunban = ports="<port>"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --remove-rich-rule="%(fwcmd_rich_rule)s"; done
rich-suffix = <rich-blocktype>

View File

@@ -0,0 +1,17 @@
[DEFAULT]
# Usage:
# _grep_logs_args = 'test'
# (printf %%b "Log-excerpt contains 'test':\n"; %(_grep_logs)s; printf %%b "Log-excerpt contains 'test':\n") | mail ...
#
_grep_logs = logpath="<logpath>"; grep <grepopts> %(_grep_logs_args)s $logpath | <greplimit>
# options `-wF` used to match only whole words and fixed string (not as pattern)
_grep_logs_args = -wF "<ip>"
# Used for actions, that should not by executed if ticket was restored:
_bypass_if_restored = if [ '<restored>' = '1' ]; then exit 0; fi;
[Init]
greplimit = tail -n <grepmax>
grepmax = 1000
grepopts = -m <grepmax>

View File

@@ -0,0 +1,62 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
# Edited for cross platform by: James Stout, Yaroslav Halchenko and Daniel Black
#
#
[Definition]
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart =
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop =
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = printf %%b "<daemon_list>: <ip_value>\n" >> <file>
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban = IP=$(echo "<ip_value>" | sed 's/[][\.]/\\\0/g') && sed -i "/^<daemon_list>: $IP$/d" <file>
[Init]
# Option: file
# Notes.: hosts.deny file path.
# Values: STR Default: /etc/hosts.deny
#
file = /etc/hosts.deny
# Option: daemon_list
# Notes: The list of services that this action will deny. See the man page
# for hosts.deny/hosts_access. Default is all services.
# Values: STR Default: ALL
daemon_list = ALL
# internal variable IP (to differentiate the IPv4 and IPv6 syntax, where it is enclosed in brackets):
ip_value = <ip>
[Init?family=inet6]
ip_value = [<ip>]

View File

@@ -0,0 +1,58 @@
# Fail2Ban configuration file
#
# NetBSD ipfilter (ipf command) ban/unban
#
# Author: Ed Ravin <eravin@panix.com>
#
#
[Definition]
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
# enable IPF if not already enabled
actionstart = /sbin/ipf -E
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
# don't disable IPF with "/sbin/ipf -D", there may be other filters in use
actionstop =
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = echo block <blocktype> in quick from <ip>/32 | /sbin/ipf -f -
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
# note -r option used to remove matching rule
actionunban = echo block <blocktype> in quick from <ip>/32 | /sbin/ipf -r -f -
[Init]
# Option: Blocktype
# Notes : This is the return-icmp[return-code] mentioned in the ipf man page section 5. Keep this quoted to prevent
# Shell expansion. This should be blank (unquoted) to drop the packet.
# Values: STRING
blocktype = "return-icmp(port-unr)"

View File

@@ -0,0 +1,68 @@
# Fail2Ban configuration file
#
# Author: Nick Munger
# Modified by: Cyril Jaquier
#
#
[Definition]
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart =
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop =
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = ipfw add <blocktype> tcp from <ip> to <localhost> <port>
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban = ipfw delete `ipfw list | grep -i "[^0-9]<ip>[^0-9]" | awk '{print $1;}'`
[Init]
# Option: port
# Notes.: specifies port to monitor
# Values: [ NUM | STRING ]
#
port = ssh
# Option: localhost
# Notes.: the local IP address of the network interface
# Values: IP
#
localhost = 127.0.0.1
# Option: blocktype
# Notes.: How to block the traffic. Use a action from man 5 ipfw
# Common values: deny, unreach port, reset
# Values: STRING
#
blocktype = unreach port

View File

@@ -0,0 +1,15 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
# Modified: Yaroslav O. Halchenko <debian@onerussian.com>
# made active on all ports from original iptables.conf
#
# Obsolete: superseded by iptables[type=allports]
[INCLUDES]
before = iptables.conf
[Definition]
type = allports

View File

@@ -0,0 +1,74 @@
# Fail2Ban configuration file
#
# Author: Daniel Black
#
# This is for ipset protocol 4 (ipset v4.2). If you have a later version
# of ipset try to use the iptables-ipset-proto6.conf as it does some things
# nicer.
#
# This requires the program ipset which is normally in package called ipset.
#
# IPset was a feature introduced in the linux kernel 2.6.39 and 3.0.0 kernels.
#
# If you are running on an older kernel you make need to patch in external
# modules. Debian squeeze can do this with:
# apt-get install xtables-addons-source
# module-assistant auto-install xtables-addons
#
# Debian wheezy and above uses protocol 6
[INCLUDES]
before = iptables.conf
[Definition]
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart = ipset --create f2b-<name> maxelem <maxelem> iphash
<_ipt_add_rules>
# Option: actionflush
# Notes.: command executed once to flush IPS, by shutdown (resp. by stop of the jail or this action)
# Values: CMD
#
actionflush = ipset --flush f2b-<name>
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop = <_ipt_del_rules>
<actionflush>
ipset --destroy f2b-<name>
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = ipset --test f2b-<name> <ip> || ipset --add f2b-<name> <ip>
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban = ipset --test f2b-<name> <ip> && ipset --del f2b-<name> <ip>
# Several capabilities used internally:
rule-jump = -m set --match-set f2b-<name> src -j <blocktype>
[Init]
# Option: maxelem
# Notes: maximal number of elements which can be stored in the ipset
# You may want to increase this for long-duration/high-volume jails
# Values: [ NUM ] Default: 65536
maxelem = 65536

View File

@@ -0,0 +1,27 @@
# Fail2Ban configuration file
#
# Author: Daniel Black
#
# This is for ipset protocol 6 (and hopefully later) (ipset v6.14).
# Use ipset -V to see the protocol and version. Version 4 should use
# iptables-ipset-proto4.conf.
#
# This requires the program ipset which is normally in package called ipset.
#
# IPset was a feature introduced in the linux kernel 2.6.39 and 3.0.0 kernels.
#
# If you are running on an older kernel you make need to patch in external
# modules which probably won't be protocol version 6.
#
# Modified: Alexander Koeppe <format_c@online.de>, Serg G. Brester <serg.brester@sebres.de>
# made config file IPv6 capable (see new section Init?family=inet6)
#
# Obsolete: superseded by iptables-ipset[type=allports]
[INCLUDES]
before = iptables-ipset.conf
[Definition]
type = allports

View File

@@ -0,0 +1,27 @@
# Fail2Ban configuration file
#
# Author: Daniel Black
#
# This is for ipset protocol 6 (and hopefully later) (ipset v6.14).
# Use ipset -V to see the protocol and version. Version 4 should use
# iptables-ipset-proto4.conf.
#
# This requires the program ipset which is normally in package called ipset.
#
# IPset was a feature introduced in the linux kernel 2.6.39 and 3.0.0 kernels.
#
# If you are running on an older kernel you make need to patch in external
# modules.
#
# Modified: Alexander Koeppe <format_c@online.de>, Serg G. Brester <serg.brester@sebres.de>
# made config file IPv6 capable (see new section Init?family=inet6)
#
# Obsolete: superseded by iptables-ipset[type=multiport]
[INCLUDES]
before = iptables-ipset.conf
[Definition]
type = multiport

View File

@@ -0,0 +1,101 @@
# Fail2Ban configuration file
#
# Authors: Sergey G Brester (sebres), Daniel Black, Alexander Koeppe
#
# This is for ipset protocol 6 (and hopefully later) (ipset v6.14).
# Use ipset -V to see the protocol and version. Version 4 should use
# iptables-ipset-proto4.conf.
#
# This requires the program ipset which is normally in package called ipset.
#
# IPset was a feature introduced in the linux kernel 2.6.39 and 3.0.0 kernels.
#
# If you are running on an older kernel you make need to patch in external
# modules.
#
[INCLUDES]
before = iptables.conf
[Definition]
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart = ipset -exist create <ipmset> <ipsettype> timeout <default-ipsettime> maxelem <maxelem> <familyopt>
<_ipt_add_rules>
# Option: actionflush
# Notes.: command executed once to flush IPS, by shutdown (resp. by stop of the jail or this action)
# Values: CMD
#
actionflush = ipset flush <ipmset>
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop = <_ipt_del_rules>
<actionflush>
ipset destroy <ipmset> 2>/dev/null || { sleep 1; ipset destroy <ipmset>; }
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = ipset -exist add <ipmset> <ip> timeout <ipsettime>
# actionprolong = %(actionban)s
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban = ipset -exist del <ipmset> <ip>
# Several capabilities used internally:
rule-jump = -m set --match-set <ipmset> src -j <blocktype>
[Init]
# Option: ipsettype
# Notes: specifies type of set, see `man --pager='less -p "^SET TYPES"' ipset` for details
# Values: hash:ip, hash:net, etc... Default: hash:ip
ipsettype = hash:ip
# Option: default-ipsettime
# Notes: specifies default timeout in seconds (handled default ipset timeout only)
# Values: [ NUM ] Default: 0 (no timeout, managed by fail2ban by unban)
default-ipsettime = 0
# Option: ipsettime
# Notes: specifies ticket timeout (handled ipset timeout only)
# Values: [ NUM ] Default: 0 (managed by fail2ban by unban)
ipsettime = 0
# Option: maxelem
# Notes: maximal number of elements which can be stored in the ipset
# You may want to increase this for long-duration/high-volume jails
# Values: [ NUM ] Default: 65536
maxelem = 65536
# expression to calculate timeout from bantime, example:
# banaction = %(known/banaction)s[ipsettime='<timeout-bantime>']
timeout-bantime = $([ "<bantime>" -le 2147483 ] && echo "<bantime>" || echo 0)
ipmset = f2b-<name>
familyopt =
[Init?family=inet6]
ipmset = f2b-<name>6
familyopt = family inet6

View File

@@ -0,0 +1,68 @@
# Fail2Ban configuration file
#
# Author: Guido Bozzetto
# Modified: Cyril Jaquier
#
# make "f2b-<name>" chain to match drop IP
# make "f2b-<name>-log" chain to log and drop
# insert a jump to f2b-<name> from -I <chain> if proto/port match
#
#
[INCLUDES]
before = iptables.conf
[Definition]
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart = <iptables> -N f2b-<name>
<iptables> -A f2b-<name> -j <returntype>
<iptables> -I <chain> 1 -p <protocol> -m multiport --dports <port> -j f2b-<name>
<iptables> -N f2b-<name>-log
<iptables> -I f2b-<name>-log -j LOG --log-prefix "$(expr f2b-<name> : '\(.\{1,23\}\)'):DROP " --log-level warning -m limit --limit 6/m --limit-burst 2
<iptables> -A f2b-<name>-log -j <blocktype>
# Option: actionflush
# Notes.: command executed once to flush IPS, by shutdown (resp. by stop of the jail or this action)
# Values: CMD
#
actionflush = <iptables> -F f2b-<name>
<iptables> -F f2b-<name>-log
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop = <iptables> -D <chain> -p <protocol> -m multiport --dports <port> -j f2b-<name>
<actionflush>
<iptables> -X f2b-<name>
<iptables> -X f2b-<name>-log
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck = <iptables> -n -L f2b-<name>-log >/dev/null
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = <iptables> -I f2b-<name> 1 -s <ip> -j f2b-<name>-log
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban = <iptables> -D f2b-<name> -s <ip> -j f2b-<name>-log
[Init]

View File

@@ -0,0 +1,14 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
# Modified by Yaroslav Halchenko for multiport banning
#
# Obsolete: superseded by iptables[type=multiport]
[INCLUDES]
before = iptables.conf
[Definition]
type = multiport

View File

@@ -0,0 +1,15 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
# Copied from iptables.conf and modified by Yaroslav Halchenko
# to fulfill the needs of bugreporter dbts#350746.
#
# Obsolete: superseded by iptables[pre-rule='-m state --state NEW<sp>']
[INCLUDES]
before = iptables.conf
[Definition]
pre-rule = -m state --state NEW<sp>

View File

@@ -0,0 +1,88 @@
# Fail2Ban configuration file
#
# Author: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
#
# Modified: Alexander Koeppe <format_c@online.de>, Serg G. Brester <serg.brester@sebres.de>
# made config file IPv6 capable
[INCLUDES]
before = iptables.conf
[Definition]
_ipt_chain_rule = -m recent --update --seconds 3600 --name <iptname> -j <blocktype>
_ipt_check_rule = <iptables> -C <chain> %(_ipt_chain_rule)s
_ipt-iter =
_ipt-done =
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
# Changing iptables rules requires root privileges. If fail2ban is
# configured to run as root, firewall setup can be performed by
# fail2ban automatically. However, if fail2ban is configured to run as
# a normal user, the configuration must be done by some other means
# (e.g. using static firewall configuration with the
# iptables-persistent package).
#
# Explanation of the rule below:
# Check if any packets coming from an IP on the <iptname>
# list have been seen in the last 3600 seconds. If yes, update the
# timestamp for this IP and drop the packet. If not, let the packet
# through.
#
# Fail2ban inserts blacklisted hosts into the <iptname> list
# and removes them from the list after some time, according to its
# own rules. The 3600 second timeout is independent and acts as a
# safeguard in case the fail2ban process dies unexpectedly. The
# shorter of the two timeouts actually matters.
actionstart = if [ `id -u` -eq 0 ];then
{ %(_ipt_check_rule)s >/dev/null 2>&1; } || { <iptables> -I <chain> %(_ipt_chain_rule)s; }
fi
# Option: actionflush
#
# [TODO] Flushing is currently not implemented for xt_recent
#
actionflush =
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop = echo / > /proc/net/xt_recent/<iptname>
if [ `id -u` -eq 0 ];then
<iptables> -D <chain> %(_ipt_chain_rule)s;
fi
# Option: actioncheck
# Notes.: command executed as invariant check (error by ban)
# Values: CMD
#
actioncheck = { %(_ipt_check_rule)s >/dev/null 2>&1; } && test -e /proc/net/xt_recent/<iptname>
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = echo +<ip> > /proc/net/xt_recent/<iptname>
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban = echo -<ip> > /proc/net/xt_recent/<iptname>
[Init]
iptname = f2b-<name>
[Init?family=inet6]
iptname = f2b-<name>6

View File

@@ -0,0 +1,163 @@
# Fail2Ban configuration file
#
# Authors: Sergey G. Brester (sebres), Cyril Jaquier, Daniel Black,
# Yaroslav O. Halchenko, Alexander Koeppe et al.
#
[Definition]
# Option: type
# Notes.: type of the action.
# Values: [ oneport | multiport | allports ] Default: oneport
#
type = oneport
# Option: actionflush
# Notes.: command executed once to flush IPS, by shutdown (resp. by stop of the jail or this action)
# Values: CMD
#
actionflush = <iptables> -F f2b-<name>
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart = { <iptables> -C f2b-<name> -j <returntype> >/dev/null 2>&1; } || { <iptables> -N f2b-<name> || true; <iptables> -A f2b-<name> -j <returntype>; }
<_ipt_add_rules>
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop = <_ipt_del_rules>
<actionflush>
<iptables> -X f2b-<name>
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck = <_ipt_check_rules>
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = <iptables> -I f2b-<name> 1 -s <ip> -j <blocktype>
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban = <iptables> -D f2b-<name> -s <ip> -j <blocktype>
# Option: pre-rule
# Notes.: prefix parameter(s) inserted to the begin of rule. No default (empty)
#
pre-rule =
rule-jump = -j <_ipt_rule_target>
# Several capabilities used internally:
_ipt-iter = for chain in $(echo '<chain>' | sed 's/,/ /g'); do for proto in $(echo '<protocol>' | sed 's/,/ /g'); do
_ipt-done = done; done
_ipt_add_rules = <_ipt-iter>
{ %(_ipt_check_rule)s >/dev/null 2>&1; } || { <iptables> -I $chain %(_ipt_chain_rule)s; }
<_ipt-done>
_ipt_del_rules = <_ipt-iter>
<iptables> -D $chain %(_ipt_chain_rule)s
<_ipt-done>
_ipt_check_rules = <_ipt-iter>
%(_ipt_check_rule)s
<_ipt-done>
_ipt_chain_rule = <pre-rule><ipt_<type>/_chain_rule>
_ipt_check_rule = <iptables> -C $chain %(_ipt_chain_rule)s
_ipt_rule_target = f2b-<name>
[ipt_oneport]
_chain_rule = -p $proto --dport <port> <rule-jump>
[ipt_multiport]
_chain_rule = -p $proto -m multiport --dports <port> <rule-jump>
[ipt_allports]
_chain_rule = -p $proto <rule-jump>
[Init]
# Option: chain
# Notes specifies the iptables chains to which the Fail2Ban rules should be
# added. May be a single chain (e.g. INPUT) or a comma separated list
# (e.g. INPUT, FORWARD)
# Values: STRING Default: INPUT
chain = INPUT
# Default name of the chain
#
name = default
# Option: port
# Notes.: specifies port to monitor
# Values: [ NUM | STRING ] Default:
#
port = ssh
# Option: protocol
# Notes.: internally used by config reader for interpolations.
# Values: [ tcp | udp | icmp | all ] Default: tcp
#
protocol = tcp
# Option: blocktype
# Note: This is what the action does with rules. This can be any jump target
# as per the iptables man page (section 8). Common values are DROP
# REJECT, REJECT --reject-with icmp-port-unreachable
# Values: STRING
blocktype = REJECT --reject-with icmp-port-unreachable
# Option: returntype
# Note: This is the default rule on "actionstart". This should be RETURN
# in all (blocking) actions, except REJECT in allowing actions.
# Values: STRING
returntype = RETURN
# Option: lockingopt
# Notes.: Option was introduced to iptables to prevent multiple instances from
# running concurrently and causing erratic behavior. -w was introduced
# in iptables 1.4.20, so might be absent on older systems
# See https://github.com/fail2ban/fail2ban/issues/1122
# Values: STRING
lockingopt = -w
# Option: iptables
# Notes.: Actual command to be executed, including common to all calls options
# Values: STRING
iptables = iptables <lockingopt>
[Init?family=inet6]
# Option: blocktype (ipv6)
# Note: This is what the action does with rules. This can be any jump target
# as per the iptables man page (section 8). Common values are DROP
# REJECT, REJECT --reject-with icmp6-port-unreachable
# Values: STRING
blocktype = REJECT --reject-with icmp6-port-unreachable
# Option: iptables (ipv6)
# Notes.: Actual command to be executed, including common to all calls options
# Values: STRING
iptables = ip6tables <lockingopt>

View File

@@ -0,0 +1,107 @@
# IPThreat configuration file
#
# Added to fail2ban by Jeff Johnson (jjxtra)
#
# Action to report IP address to ipthreat.net
#
# You must sign up to obtain an API key from ipthreat.net and request bulk report permissions
# https://ipthreat.net/integrations
#
# IPThreat is a 100% free site and service, all data is licensed under a creative commons by attribution license
# Please do not integrate if you do not agree to the license
#
# IMPORTANT:
#
# Reporting an IP is a serious action. Make sure that it is legit.
# Consider using this action only for:
# * IP that has been banned more than once
# * High max retry to avoid user mistyping password
# * Filters that are unlikely to be human error
#
# Example:
# ```
# action = %(known/action)s
# ipthreat[]
# ```
#
# The action accepts the following arguments: ipthreat[ipthreat_flags="8",ipthreat_system="SSH", ipthreat_apikey=...]
# In most cases your action could be as simple as: ipthreat[], since the default flags and system are set to the most correct default values.
# You can optionally override ipthreat_system and ipthreat_flags if desired.
# The ipthreat_apikey must be set at the bottom of this configuration file.
#
# `ipthreat_system` is a short name of the system attacked, i.e. SSH, SMTP, MYSQL, PHP, etc.
#
# For `ipthreat_flags`, most cases will use 8 (BruteForce) which is the default, but you could use others.
# You can use the name or the ordinal.
# Multiple values are comma separated.
# ```
# Name Ordinal Description
# Dns 1 Abuse/attack of dns (domain name server)
# Fraud 2 General fraud, whether orders, misuse of payment info, etc
# DDos 4 Distributed denial of service attack, whether through http requests, large ping attack, etc
# BruteForce 8 Brute force login attack
# Proxy 16 IP is a proxy like TOR or other proxy server
# Spam 32 Email, comment or other type of spam
# Vpn 64 IP is part of a VPN
# Hacking 128 General hacking outside of brute force attack (includes vulnerability scans, sql injection, etc.). Use port scan flag instead if it's just probe on ports.
# BadBot 256 Bad bot that is not honoring robots.txt or just flooding with too many requests, etc
# Compromised 512 The ip has been taken over by malware or botnet
# Phishing 1024 The ip is involved in phishing or spoofing
# Iot 2048 The ip has targeted an iot (Internet of Things) device
# PortScan 4096 Port scan
# See https://ipthreat.net/bulkreportformat for more information
# ```
[Definition]
# bypass action for restored tickets
norestored = 1
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart =
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop =
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
#
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = curl -sSf "https://api.ipthreat.net/api/report" -X POST -H "Content-Type: application/json" -H "X-API-KEY: <ipthreat_apikey>" -d "{\"ip\":\"<ip>\",\"flags\":\"<ipthreat_flags>\",\"system\":\"<ipthreat_system>\",\"notes\":\"fail2ban\"}"
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban =
[Init]
# Option: ipthreat_apikey
# Notes Your API key from ipthreat.net
# Values: STRING Default: None
# Register for ipthreat [https://ipthreat.net], get api key and set below.
# You will need to set the flags and system in the action call in jail.conf
ipthreat_apikey =
# By default, the ipthreat system is the name of the fail2ban jail
ipthreat_system = <name>
# By default the ip threat flags is 8 (brute force), but you can override this per jail if desired
ipthreat_flags = 8

View File

@@ -0,0 +1,86 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
#
[Definition]
# bypass ban/unban for restored tickets
norestored = 1
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart = printf %%b "Hi,\n
The jail <name> has been started successfully.\n
Output will be buffered until <lines> lines are available.\n
Regards,\n
Fail2Ban"|mail -E 'set escape' -s "[Fail2Ban] <name>: started on <fq-hostname>" <dest>
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop = if [ -f <tmpfile> ]; then
printf %%b "Hi,\n
These hosts have been banned by Fail2Ban.\n
`cat <tmpfile>`
Regards,\n
Fail2Ban"|mail -E 'set escape' -s "[Fail2Ban] <name>: Summary from <fq-hostname>" <dest>
rm <tmpfile>
fi
printf %%b "Hi,\n
The jail <name> has been stopped.\n
Regards,\n
Fail2Ban"|mail -E 'set escape' -s "[Fail2Ban] <name>: stopped on <fq-hostname>" <dest>
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = printf %%b "`date`: <ip> (<failures> failures)\n" >> <tmpfile>
LINE=$( wc -l <tmpfile> | awk '{ print $1 }' )
if [ $LINE -ge <lines> ]; then
printf %%b "Hi,\n
These hosts have been banned by Fail2Ban.\n
`cat <tmpfile>`
\nRegards,\n
Fail2Ban"|mail -E 'set escape' -s "[Fail2Ban] <name>: Summary" <dest>
rm <tmpfile>
fi
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban =
[Init]
# Default name of the chain
#
name = default
# Default number of lines that are buffered
#
lines = 5
# Default temporary file
#
tmpfile = /var/run/fail2ban/tmp-mail.txt
# Destination/Addressee of the mail
#
dest = root

View File

@@ -0,0 +1,28 @@
# Fail2Ban configuration file
#
# Common settings for mail actions
#
# Users can override the defaults in mail-whois-common.local
[INCLUDES]
# Load customizations if any available
after = mail-whois-common.local
[DEFAULT]
#original character set of whois output will be sent to mail program
_whois = whois <ip> || echo "missing whois program"
# use heuristics to convert charset of whois output to a target
# character set before sending it to a mail program
# make sure you have 'file' and 'iconv' commands installed when opting for that
_whois_target_charset = UTF-8
_whois_convert_charset = (%(_whois)s) |
{ WHOIS_OUTPUT=$(cat) ; WHOIS_CHARSET=$(printf %%b "$WHOIS_OUTPUT" | file -b --mime-encoding -) ; printf %%b "$WHOIS_OUTPUT" | iconv -f $WHOIS_CHARSET -t %(_whois_target_charset)s//TRANSLIT - ; }
# choose between _whois and _whois_convert_charset in mail-whois-common.local
# or other *.local which include mail-whois-common.conf.
_whois_command = %(_whois)s
#_whois_command = %(_whois_convert_charset)s
[Init]

View File

@@ -0,0 +1,92 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
# Modified-By: Yaroslav Halchenko to include grepping on IP over log files
#
[INCLUDES]
before = mail-whois-common.conf
helpers-common.conf
[Definition]
# bypass ban/unban for restored tickets
norestored = 1
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart = printf %%b "Hi,\n
The jail <name> has been started successfully.\n
Regards,\n
Fail2Ban" | <mailcmd> "[Fail2Ban] <name>: started on <fq-hostname>" <dest>
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop = printf %%b "Hi,\n
The jail <name> has been stopped.\n
Regards,\n
Fail2Ban" | <mailcmd> "[Fail2Ban] <name>: stopped on <fq-hostname>" <dest>
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
_ban_mail_content = ( printf %%b "Hi,\n
The IP <ip> has just been banned by Fail2Ban after
<failures> attempts against <name>.\n\n
Here is more information about <ip> :\n"
%(_whois_command)s;
printf %%b "\nLines containing failures of <ip> (max <grepmax>)\n";
%(_grep_logs)s;
printf %%b "\n
Regards,\n
Fail2Ban" )
actionban = %(_ban_mail_content)s | <mailcmd> "[Fail2Ban] <name>: banned <ip> from <fq-hostname>" <dest>
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban =
[Init]
# Option: mailcmd
# Notes.: Your system mail command. Is passed 2 args: subject and recipient
# Values: CMD
#
mailcmd = mail -E 'set escape' -s
# Default name of the chain
#
name = default
# Destinataire of the mail
#
dest = root
# Path to the log files which contain relevant lines for the abuser IP
#
logpath = /dev/null
# Number of log lines to include in the email
#
#grepmax = 1000
#grepopts = -m <grepmax>

View File

@@ -0,0 +1,71 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
#
[INCLUDES]
before = mail-whois-common.conf
[Definition]
# bypass ban/unban for restored tickets
norestored = 1
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart = printf %%b "Hi,\n
The jail <name> has been started successfully.\n
Regards,\n
Fail2Ban"|mail -E 'set escape' -s "[Fail2Ban] <name>: started on <fq-hostname>" <dest>
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop = printf %%b "Hi,\n
The jail <name> has been stopped.\n
Regards,\n
Fail2Ban"|mail -E 'set escape' -s "[Fail2Ban] <name>: stopped on <fq-hostname>" <dest>
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = printf %%b "Hi,\n
The IP <ip> has just been banned by Fail2Ban after
<failures> attempts against <name>.\n\n
Here is more information about <ip> :\n
`%(_whois_command)s`\n
Regards,\n
Fail2Ban"|mail -E 'set escape' -s "[Fail2Ban] <name>: banned <ip> from <fq-hostname>" <dest>
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban =
[Init]
# Default name of the chain
#
name = default
# Destination/Addressee of the mail
#
dest = root

View File

@@ -0,0 +1,65 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
#
[Definition]
# bypass ban/unban for restored tickets
norestored = 1
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart = printf %%b "Hi,\n
The jail <name> has been started successfully.\n
Regards,\n
Fail2Ban"|mail -E 'set escape' -s "[Fail2Ban] <name>: started on <fq-hostname>" <dest>
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop = printf %%b "Hi,\n
The jail <name> has been stopped.\n
Regards,\n
Fail2Ban"|mail -E 'set escape' -s "[Fail2Ban] <name>: stopped on <fq-hostname>" <dest>
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = printf %%b "Hi,\n
The IP <ip> has just been banned by Fail2Ban after
<failures> attempts against <name>.\n
Regards,\n
Fail2Ban"|mail -E 'set escape' -s "[Fail2Ban] <name>: banned <ip> from <fq-hostname>" <dest>
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban =
[Init]
# Default name of the chain
#
name = default
# Destination/Addressee of the mail
#
dest = root

View File

@@ -0,0 +1,84 @@
# Fail2Ban configuration file
#
# Mikrotik routerOS action to add/remove address-list entries
#
# Author: Duncan Bellamy <dunk@denkimushi.com>
# based on forum.mikrotik.com post by pakjebakmeel
#
# in the instructions:
# (10.0.0.1 is ip of mikrotik router)
# (10.0.0.2 is ip of fail2ban machine)
#
# on fail2ban machine:
# sudo mkdir /var/lib/fail2ban/ssh
# sudo chmod 700 /var/lib/fail2ban/ssh
# sudo ssh-keygen -N "" -f /var/lib/fail2ban/ssh/fail2ban_id_rsa
# sudo scp /var/lib/fail2ban/ssh/fail2ban_id_rsa.pub admin@10.0.0.1:/
# ssh admin@10.0.0.1
#
# on mikrotik router:
# /user add name=miki-f2b group=write address=10.0.0.2 password=""
# /user ssh-keys import public-key-file=fail2ban_id_rsa.pub user=miki-f2b
# /quit
#
# on fail2ban machine:
# (check password login fails)
# ssh miki-f2b@10.0.0.1
# (check private key works)
# sudo ssh -i /var/lib/fail2ban/ssh/fail2ban_id_rsa miki-f2b@10.0.0.1
#
# Then create rules on mikrorik router that use address
# list(s) maintained by fail2ban eg in the forward chain
# drop from address list, or in the forward chain drop
# from address list to server
#
# example extract from jail.local overriding some defaults
# action = mikrotik[keyfile="%(mkeyfile)s", user="%(muser)s", host="%(mhost)s", list="%(mlist)s"]
#
# ignoreip = 127.0.0.1/8 192.168.0.0/24
# mkeyfile = /etc/fail2ban/ssh/mykey_id_rsa
# muser = myuser
# mhost = 192.168.0.1
# mlist = BAD LIST
[Definition]
actionstart =
actionstop = %(actionflush)s
actionflush = %(command)s "/ip firewall address-list remove [find list=\"%(list)s\" comment~\"%(startcomment)s-*\"]"
actioncheck =
actionban = %(command)s "/ip firewall address-list add list=\"%(list)s\" address=<ip> comment=%(comment)s"
actionunban = %(command)s "/ip firewall address-list remove [find list=\"%(list)s\" comment=%(comment)s]"
command = ssh -l %(user)s -p%(port)s -i %(keyfile)s %(host)s
# Option: user
# Notes.: username to use when connecting to routerOS
user =
# Option: port
# Notes.: port to use when connecting to routerOS
port = 22
# Option: keyfile
# Notes.: ssh private key to use for connecting to routerOS
keyfile =
# Option: host
# Notes.: hostname or ip of router
host =
# Option: list
# Notes.: name of "address-list" to use on router
list = Fail2Ban
# Option: startcomment
# Notes.: used as a prefix to all comments, and used to match for flushing rules
startcomment = f2b-<name>
# Option: comment
# Notes.: comment to use on routerOS (must be unique as used for ip address removal)
comment = %(startcomment)s-<ip>
[Init]
name="%(__name__)s"

View File

@@ -0,0 +1,143 @@
# Fail2Ban configuration file
#
# Author: Russell Odom <russ@gloomytrousers.co.uk>
# Submits attack reports to myNetWatchman (http://www.mynetwatchman.com/)
#
# You MUST configure at least:
# <port> (the port that's being attacked - use number not name).
# <mnwlogin> (your mNW login).
# <mnwpass> (your mNW password).
#
# You SHOULD also provide:
# <myip> (your public IP address, if it's not the address of eth0)
# <protocol> (the protocol in use - defaults to tcp)
#
# Best practice is to provide <port> and <protocol> in jail.conf like this:
# action = mynetwatchman[port=1234,protocol=udp]
#
# ...and create "mynetwatchman.local" with contents something like this:
# [Init]
# mnwlogin = me@example.com
# mnwpass = SECRET
# myip = 10.0.0.1
#
# Another useful configuration value is <getcmd>, if you don't have wget
# installed (an example config for curl is given below)
#
[Definition]
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart =
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop =
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
#
# Note: We are currently using <time> for the timestamp because no tag is
# available to indicate the timestamp of the log message(s) which triggered the
# ban. Therefore the timestamps we are using in the report, whilst often only a
# few seconds out, are incorrect. See
# http://sourceforge.net/tracker/index.php?func=detail&aid=2017795&group_id=121032&atid=689047
#
actionban = MNWLOGIN=`perl -e '$s=shift;$s=~s/([\W])/"%%".uc(sprintf("%%2.2x",ord($1)))/eg;print $s' '<mnwlogin>'`
MNWPASS=`perl -e '$s=shift;$s=~s/([\W])/"%%".uc(sprintf("%%2.2x",ord($1)))/eg;print $s' '<mnwpass>'`
PROTOCOL=`awk '{IGNORECASE=1;if($1=="<protocol>"){print $2;exit}}' /etc/protocols`
if [ -z "$PROTOCOL" ]; then PROTOCOL=<protocol>; fi
DATETIME=`perl -e '@t=gmtime(<time>);printf "%%4d-%%02d-%%02d+%%02d:%%02d:%%02d",1900+$t[5],$t[4]+1,$t[3],$t[2],$t[1],$t[0]'`
<getcmd> "<mnwurl>?AT=2&AV=0&AgentEmail=$MNWLOGIN&AgentPassword=$MNWPASS&AttackerIP=<ip>&SrcPort=<srcport>&ProtocolID=$PROTOCOL&DestPort=<port>&AttackCount=<failures>&VictimIP=<myip>&AttackDateTime=$DATETIME" 2>&1 >> <tmpfile>.out && grep -q 'Attack Report Insert Successful' <tmpfile>.out && rm -f <tmpfile>.out
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban =
[Init]
# Option: port
# Notes.: The target port for the attack (numerical). MUST be provided in
# the jail config, as it cannot be detected here.
# Values: [ NUM ] Default: ???
#
port = 0
# Option: mnwlogin
# Notes.: Your mNW login e-mail address. MUST be provided either in the jail
# config or in a .local file.
# Register at http://www.mynetwatchman.com/reg.asp
# Values: [ STRING ] Default: (empty)
#
mnwlogin =
# Option: mnwpass
# Notes.: The password corresponding to your mNW login e-mail address. MUST be
# provided either in the jail config or in a .local file.
# Values: [ STRING ] Default: (empty)
#
mnwpass =
# Option: myip
# Notes.: The target IP for the attack (your public IP). Should be overridden
# either in the jail config or in a .local file unless your PUBLIC IP
# is the first IP assigned to eth0
# Values: [ an IP address ] Default: Tries to find the IP address of eth0,
# which in most cases will be a private IP, and therefore incorrect
#
myip = `ip -4 addr show dev eth0 | grep inet | head -n 1 | sed -r 's/.*inet ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*/\1/'`
# Option: protocol
# Notes.: The protocol over which the attack is happening
# Values: [ tcp | udp | icmp | (any other protocol name from /etc/protocols) | NUM ] Default: tcp
#
protocol = tcp
# Option: agent
# Default: Fail2ban
agent = Fail2ban
# Option: getcmd
# Notes.: A command to fetch a URL. Should output page to STDOUT
# Values: CMD Default: wget
#
getcmd = wget --no-verbose --tries=3 --waitretry=10 --connect-timeout=10 --read-timeout=60 --retry-connrefused --output-document=- --user-agent=<agent>
# Alternative value:
# getcmd = curl --silent --show-error --retry 3 --connect-timeout 10 --max-time 60 --user-agent <agent>
# Option: srcport
# Notes.: The source port of the attack. You're unlikely to have this info, so
# you can leave the default
# Values: [ NUM ] Default: 0
#
srcport = 0
# Option: mnwurl
# Notes.: The report service URL on the mNW site
# Values: STRING Default: http://mynetwatchman.com/insertwebreport.asp
#
mnwurl = http://mynetwatchman.com/insertwebreport.asp
# Option: tmpfile
# Notes.: Base name of temporary files
# Values: [ STRING ] Default: /var/run/fail2ban/tmp-mynetwatchman
#
tmpfile = /var/run/fail2ban/tmp-mynetwatchman

View File

@@ -0,0 +1,33 @@
# Fail2ban Citrix Netscaler Action
# by Juliano Jeziorny
# juliano@jeziorny.eu
#
# The script will add offender IPs to a dataset on netscaler, the dataset can then be used to block the IPs at a cs/vserver or global level
# This dataset is then used to block IPs using responder policies on the netscaler.
#
# The script assumes using HTTPS with insecure certificate to access the netscaler,
# if you have a valid certificate installed remove the -k from the curl lines, or if you want http change it accordingly (and remove the -k)
#
# This action depends on curl
#
# You need to populate the 3 options inside Init
#
# ns_host: IP or hostname of netslcaer appliance
# ns_auth: username:password, suggest base64 encoded for a little added security (echo -n "username:password" | base64)
# ns_dataset: Name of the netscaler dataset holding the IPs to be blocked.
#
# For further details on how to use it please check http://blog.ckzone.eu/2017/01/fail2ban-action-for-citrix-netscaler.html
[Init]
ns_host =
ns_auth =
ns_dataset =
[Definition]
actionstart = curl -kH 'Authorization: Basic <ns_auth>' https://<ns_host>/nitro/v1/config
actioncheck =
actionban = curl -k -H 'Authorization: Basic <ns_auth>' -X PUT -d '{"policydataset_value_binding":{"name":"<ns_dataset>","value":"<ip>"}}' https://<ns_host>/nitro/v1/config/
actionunban = curl -H 'Authorization: Basic <ns_auth>' -X DELETE -k "https://<ns_host>/nitro/v1/config/policydataset_value_binding/<ns_dataset>?args=value:<ip>"

View File

@@ -0,0 +1,17 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
# Modified: Yaroslav O. Halchenko <debian@onerussian.com>
# made active on all ports from original iptables.conf
# Modified: Alexander Belykh <albel727@ngs.ru>
# adapted for nftables
#
# Obsolete: superseded by nftables[type=allports]
[INCLUDES]
before = nftables.conf
[Definition]
type = allports

View File

@@ -0,0 +1,17 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
# Modified: Yaroslav O. Halchenko <debian@onerussian.com>
# made active on all ports from original iptables.conf
# Modified: Alexander Belykh <albel727@ngs.ru>
# adapted for nftables
#
# Obsolete: superseded by nftables[type=multiport]
[INCLUDES]
before = nftables.conf
[Definition]
type = multiport

View File

@@ -0,0 +1,208 @@
# Fail2Ban configuration file
#
# Author: Daniel Black
# Author: Cyril Jaquier
# Modified: Yaroslav O. Halchenko <debian@onerussian.com>
# made active on all ports from original iptables.conf
# Modified: Alexander Belykh <albel727@ngs.ru>
# adapted for nftables
#
# This is a included configuration file and includes the definitions for the nftables
# used in all nftables based actions by default.
#
# The user can override the defaults in nftables-common.local
# Example: redirect flow to honeypot
#
# [Init]
# table_family = ip
# chain_type = nat
# chain_hook = prerouting
# chain_priority = -50
# blocktype = counter redirect to 2222
[INCLUDES]
after = nftables-common.local
[Definition]
# Option: type
# Notes.: type of the action.
# Values: [ multiport | allports ] Default: multiport
#
type = multiport
rule_match-custom =
rule_match-allports = meta l4proto \{ <protocol> \}
rule_match-multiport = $proto dport \{ $(echo '<port>' | sed s/:/-/g) \}
match = <rule_match-<type>>
# Option: rule_stat
# Notes.: statement for nftables filter rule.
# leaving it empty will block all (include udp and icmp)
# Values: nftables statement
#
rule_stat = %(match)s <addr_family> saddr @<addr_set> <blocktype>
# optional iterator over protocol's:
_nft_for_proto-custom-iter =
_nft_for_proto-custom-done =
_nft_for_proto-allports-iter =
_nft_for_proto-allports-done =
_nft_for_proto-multiport-iter = for proto in $(echo '<protocol>' | sed 's/,/ /g'); do
_nft_for_proto-multiport-done = done
_nft_list = <nftables> -a list chain <table_family> <table> <chain>
_nft_get_handle_id = sed -nE 's/.*@<addr_set>\s+.*\s+\#\s*(handle\s+[0-9]+)$/\1/p'
_nft_add_set = <nftables> add set <table_family> <table> <addr_set> \{ type <addr_type>\;<addr_options> \}
<_nft_for_proto-<type>-iter>
<nftables> add rule <table_family> <table> <chain> %(rule_stat)s
<_nft_for_proto-<type>-done>
_nft_del_set = { %(_nft_list)s | %(_nft_get_handle_id)s; } | while read -r hdl; do
<nftables> delete rule <table_family> <table> <chain> $hdl; done
<nftables> delete set <table_family> <table> <addr_set>
# Option: _nft_shutdown_table
# Notes.: command executed after the stop in order to delete table (it checks that no sets are available):
# Values: CMD
#
_nft_shutdown_table = { <nftables> list table <table_family> <table> | grep -qE '^\s+set\s+'; } || {
<nftables> delete table <table_family> <table>
}
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart = <nftables> add table <table_family> <table>
<nftables> -- add chain <table_family> <table> <chain> \{ type <chain_type> hook <chain_hook> priority <chain_priority> \; \}
%(_nft_add_set)s
# Option: actionflush
# Notes.: command executed once to flush IPS, by shutdown (resp. by stop of the jail or this action);
# uses `nft flush set ...` and as fallback (e. g. unsupported) recreates the set (with references)
# Values: CMD
#
actionflush = { <nftables> flush set <table_family> <table> <addr_set> 2> /dev/null; } || {
%(_nft_del_set)s
%(_nft_add_set)s
}
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop = %(_nft_del_set)s
<_nft_shutdown_table>
# Option: actioncheck
# Notes.: command executed once in error case by other command (during the check/restore sane environment process)
# Values: CMD
#
actioncheck = <nftables> list chain <table_family> <table> <chain> | grep -q '@<addr_set>[ \t]'
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = <nftables> add element <table_family> <table> <addr_set> \{ <ip> \}
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban = <nftables> delete element <table_family> <table> <addr_set> \{ <ip> \}
[Init]
# Option: table
# Notes.: main table to store chain and sets (automatically created on demand)
# Values: STRING Default: f2b-table
table = f2b-table
# Option: table_family
# Notes.: address family to work in
# Values: [ip | ip6 | inet] Default: inet
table_family = inet
# Option: chain
# Notes.: main chain to store rules
# Values: STRING Default: f2b-chain
chain = f2b-chain
# Option: chain_type
# Notes.: refers to the kind of chain to be created
# Values: [filter | route | nat] Default: filter
#
chain_type = filter
# Option: chain_hook
# Notes.: refers to the kind of chain to be created
# Values: [ prerouting | input | forward | output | postrouting ] Default: input
#
chain_hook = input
# Option: chain_priority
# Notes.: priority in the chain.
# Values: NUMBER Default: -1
#
chain_priority = -1
# Option: addr_type
# Notes.: address type to work with
# Values: [ipv4_addr | ipv6_addr] Default: ipv4_addr
#
addr_type = ipv4_addr
# Default name of the filtering set
#
name = default
# Option: port
# Notes.: specifies port to monitor
# Values: [ NUM | STRING ] Default:
#
port = ssh
# Option: protocol
# Notes.: internally used by config reader for interpolations.
# Values: [ tcp | udp ] Default: tcp
#
protocol = tcp
# Option: blocktype
# Note: This is what the action does with rules. This can be any jump target
# as per the nftables man page (section 8). Common values are drop,
# reject, reject with icmpx type host-unreachable, redirect to 2222
# Values: STRING
blocktype = reject
# Option: nftables
# Notes.: Actual command to be executed, including common to all calls options
# Values: STRING
nftables = nft
# Option: addr_set
# Notes.: The name of the nft set used to store banned addresses
# Values: STRING
addr_set = addr-set-<name>
# Option: addr_family
# Notes.: The family of the banned addresses
# Values: [ ip | ip6 ]
addr_family = ip
# Option: addr_options
# Notes: Additional options for the addr-set, by default allows to store CIDR or address ranges.
# Can be set to empty value to create simple addresses set.
addr_options = <sp>flags interval\;
[Init?family=inet6]
addr_family = ip6
addr_type = ipv6_addr
addr_set = addr6-set-<name>

View File

@@ -0,0 +1,117 @@
# Fail2Ban configuration file for black-listing via nginx
#
# Author: Serg G. Brester (aka sebres)
#
# To use 'nginx-block-map' action you should define some special blocks in your nginx configuration,
# and use it hereafter in your locations (to notify fail2ban by failure, resp. nginx by ban).
#
# Example (argument "token_id" resp. cookie "session_id" used here as unique identifier for user):
#
# http {
# ...
# # maps to check user is blacklisted (banned in f2b):
# #map $arg_token_id $blck_lst_tok { include blacklisted-tokens.map; }
# map $cookie_session_id $blck_lst_ses { include blacklisted-sessions.map; }
# ...
# # special log-format to notify fail2ban about failures:
# log_format f2b_session_errors '$msec failure "$cookie_session_id" - $remote_addr - $remote_user '
# ;# '"$request" $status $bytes_sent '
# # '"$http_referer" "$http_user_agent"';
#
# # location checking blacklisted values:
# location ... {
# # check banned sessionid:
# if ($blck_lst_ses != "") {
# try_files "" @f2b-banned;
# }
# ...
# # notify fail2ban about a failure inside nginx:
# error_page 401 = @notify-f2b;
# ...
# }
# ...
# # location for return with "403 Forbidden" if banned:
# location @f2b-banned {
# default_type text/html;
# return 403 "<br/><center>
# <b style=\"color:red; font-size:18pt; border:2pt solid black; padding:5pt;\">
# You are banned!</b></center>";
# }
# ...
# # location to notify fail2ban about a failure inside nginx:
# location @notify-f2b {
# access_log /var/log/nginx/f2b-auth-errors.log f2b_session_errors;
# }
# }
# ...
#
# Note that quote-character (and possibly other special characters) are not allowed currently as session-id.
# Thus please add any session-id validation rule in your locations (or in the corresponding backend-service),
# like in example below:
#
# location ... {
# if ($cookie_session_id !~ "^[\w\-]+$") {
# return 403 "Wrong session-id"
# }
# ...
# }
#
# The parameters for jail corresponding log-format (f2b_session_errors):
#
# [nginx-blck-lst]
# filter =
# datepattern = ^Epoch
# failregex = ^ failure "<F-ID>[^"]+</F-ID>" - <ADDR>
# usedns = no
#
# The same log-file can be used for IP-related jail (additionally to session-related, to ban very bad IPs):
#
# [nginx-blck-ip]
# maxretry = 100
# filter =
# datepattern = ^Epoch
# failregex = ^ failure "[^"]+" - <ADDR>
# usedns = no
#
[Definition]
# path to configuration of nginx (used to target nginx-instance in multi-instance system,
# and as path for the blacklisted map):
srv_cfg_path = /etc/nginx/
# cmd-line arguments to supply to test/reload nginx:
#srv_cmd = nginx -c %(srv_cfg_path)s/nginx.conf
srv_cmd = nginx
# pid file (used to check nginx is running):
srv_pid = /run/nginx.pid
# command used to check whether nginx is running and configuration is valid:
srv_is_running = [ -f "%(srv_pid)s" ]
srv_check_cmd = %(srv_is_running)s && %(srv_cmd)s -qt
# first test nginx is running and configuration is correct, hereafter send reload signal:
blck_lst_reload = %(srv_check_cmd)s; if [ $? -eq 0 ]; then
%(srv_cmd)s -s reload; if [ $? -ne 0 ]; then echo 'reload failed.'; fi;
fi;
# map-file for nginx, can be redefined using `action = nginx-block-map[blck_lst_file="/path/file.map"]`:
blck_lst_file = %(srv_cfg_path)s/blacklisted-sessions.map
# Action definition:
actionstart_on_demand = false
actionstart = touch '%(blck_lst_file)s'
actionflush = truncate -s 0 '%(blck_lst_file)s'; %(blck_lst_reload)s
actionstop = %(actionflush)s
actioncheck =
_echo_blck_row = printf '\%%s 1;\n' "<fid>"
actionban = %(_echo_blck_row)s >> '%(blck_lst_file)s'; %(blck_lst_reload)s
actionunban = id=$(%(_echo_blck_row)s | sed -e 's/[]\/$*.^|[]/\\&/g'); sed -i "/^$id$/d" %(blck_lst_file)s; %(blck_lst_reload)s

View File

@@ -0,0 +1,61 @@
# Fail2Ban configuration file
#
# NetBSD npf ban/unban
#
# Author: Nils Ratusznik <nils@NetBSD.org>
# Based on pf.conf action file
#
[Definition]
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
# we don't enable NPF automatically, as it will be enabled elsewhere
actionstart =
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
# we don't disable NPF automatically either
actionstop =
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: <ip> IP address
# <failures> number of failures
# <time> unix timestamp of the ban time
# Values: CMD
#
actionban = /sbin/npfctl table <tablename> add <ip>
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: <ip> IP address
# <failures> number of failures
# <time> unix timestamp of the ban time
# Values: CMD
#
# note -r option used to remove matching rule
actionunban = /sbin/npfctl table <tablename> rem <ip>
[Init]
# Option: tablename
# Notes.: The pf table name.
# Values: [ STRING ]
#
tablename = fail2ban

View File

@@ -0,0 +1,114 @@
# Fail2Ban configuration file
#
# Author: Andrew St. Jean
#
# Use nsupdate to perform dynamic DNS updates on a BIND zone file.
# One may want to do this to update a local RBL with banned IP addresses.
#
# Options
#
# domain DNS domain that will appear in nsupdate add and delete
# commands.
#
# ttl The time to live (TTL) in seconds of the TXT resource
# record.
#
# rdata Data portion of the TXT resource record.
#
# nsupdatecmd Full path to the nsupdate command.
#
# keyfile Full path to TSIG key file used for authentication between
# nsupdate and BIND.
#
# Create an nsupdate.local to set at least the <domain> and <keyfile>
# options as they don't have default values.
#
# The ban and unban commands assume nsupdate will authenticate to the BIND
# server using a TSIG key. The full path to the key file must be specified
# in the <keyfile> parameter. Use this command to generate your TSIG key.
#
# dnssec-keygen -a HMAC-MD5 -b 256 -n HOST <key_name>
#
# Replace <key_name> with some meaningful name.
#
# This command will generate two files. Specify the .private file in the
# <keyfile> option. Note that the .key file must also be present in the same
# directory for nsupdate to use the key.
#
# Don't forget to add the key and appropriate allow-update or update-policy
# option to your named.conf file.
#
[Definition]
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart =
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop =
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = echo <ip> | awk -F. '{print "prereq nxrrset "$4"."$3"."$2"."$1".<domain> TXT"; print "update add "$4"."$3"."$2"."$1".<domain> <ttl> IN TXT \"<rdata>\""; print "send"}' | <nsupdatecmd> -k <keyfile>
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban = echo <ip> | awk -F. '{print "update delete "$4"."$3"."$2"."$1".<domain>"; print "send"}' | <nsupdatecmd> -k <keyfile>
[Init]
# Option: domain
# Notes.: DNS domain that nsupdate will update.
# Values: STRING
#
domain =
# Option: ttl
# Notes.: time to live (TTL) in seconds of TXT resource record
# added by nsupdate.
# Values: NUM
#
ttl = 60
# Option: rdata
# Notes.: data portion of the TXT resource record added by nsupdate.
# Values: STRING
#
rdata = Your IP has been banned
# Option: nsupdatecmd
# Notes.: specifies the full path to the nsupdate program that dynamically
# updates BIND zone files.
# Values: CMD
#
nsupdatecmd = /usr/bin/nsupdate
# Option: keyfile
# Notes.: specifies the full path to the file containing the
# TSIG key for communicating with BIND.
# Values: STRING
#
keyfile =

View File

@@ -0,0 +1,16 @@
# Fail2Ban configuration file for using afctl on Mac OS X Server 10.5
#
# Anonymous author
# http://www.fail2ban.org/wiki/index.php?title=HOWTO_Mac_OS_X_Server_(10.5)&diff=prev&oldid=4081
#
# Ref: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man8/afctl.8.html
[Definition]
actionstart =
actionstop =
actioncheck =
actionban = /usr/libexec/afctl -a <ip> -t <bantime>
actionunban = /usr/libexec/afctl -r <ip>
actionprolong = %(actionunban)s && %(actionban)s

View File

@@ -0,0 +1,87 @@
# Fail2Ban configuration file
#
# Author: Nick Munger
# Modified by: Andy Fragen and Daniel Black
#
# Mod for OS X, using random rulenum as OSX ipfw doesn't include tables
#
[Definition]
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart =
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop =
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: <ip> IP address
# Values: CMD
#
actionban = ipfw add <rulenum> set <setnum> <blocktype> log <block> from <ip> to <dst> <port>
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: <ip> IP address
# Values: CMD
#
actionunban = ipfw delete `ipfw -S list | grep -i 'set <setnum> <blocktype> log <block> from <ip> to <dst>' | awk '{print $1;}'`
[Init]
# Option: port
# Notes.: specifies port to block. Can be blank however may require block="ip"
# Values: [ NUM | STRING ]
#
port = ssh
# Option: dst
# Notes.: the local IP address of the network interface
# Values: IP, any, me or anything support by ipfw as a dst
#
dst = me
# Option: block
# Notes: This is how much to block.
# Can be "ip", "tcp", "udp" or various other options.
# Values: STRING
block = tcp
# Option: blocktype
# Notes.: How to block the traffic. Use a action from man 8 ipfw
# Common values: deny, unreach port, reset
# Values: STRING
#
blocktype = unreach port
# Option: set number
# Notes.: The ipset number this is added to.
# Values: 0-31
setnum = 10
# Option: number for ipfw rule
# Notes: This is meant to be automatically generated and not overwritten
# Values: Random value between 10000 and 12000
rulenum="`echo $((RANDOM%%2000+10000))`"
# Duplicate prevention mechanism
#rulenum = "`a=$((RANDOM%%2000+10000)); while ipfw show | grep -q ^$a\ ; do a=$((RANDOM%%2000+10000)); done; echo $a`"

View File

@@ -0,0 +1,128 @@
# Fail2Ban configuration file
#
# OpenBSD pf ban/unban
#
# Author: Nick Hilliard <nick@foobar.org>
# Modified by: Alexander Koeppe making PF work seamless and with IPv4 and IPv6
# Modified by: Balazs Mateffy adding allproto option so all traffic gets blocked from the malicious source
#
#
[Definition]
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
# we don't enable PF automatically; to enable run pfctl -e
# or add `pf_enable="YES"` to /etc/rc.conf (tested on FreeBSD)
# also, these rulesets are loaded into (nested) anchors
# to enable them, add as wildcard:
# anchor "f2b/*"
# or using jail names:
# anchor f2b {
# anchor name1
# anchor name2
# ...
# }
# to your main pf ruleset, where "namei" are the names of the jails
# which invoke this action
# to block all protocols use the pf[protocol=all] option
actionstart = echo "table <<tablename>-<name>> persist counters" | <pfctl> -f-
port="<port>"; if [ "$port" != "" ] && case "$port" in \{*) false;; esac; then port="{$port}"; fi
protocol="<protocol>"; if [ "$protocol" != "all" ]; then protocol="proto $protocol"; else protocol=all; fi
echo "<block> $protocol from <<tablename>-<name>> to <actiontype>" | <pfctl> -f-
# Option: start_on_demand - to start action on demand
# Example: `action=pf[actionstart_on_demand=true]`
actionstart_on_demand = false
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
# we only disable PF rules we've installed prior
actionstop = <pfctl> -sr 2>/dev/null | grep -v <tablename>-<name> | <pfctl> -f-
%(actionflush)s
<pfctl> -t <tablename>-<name> -T kill
# Option: actionflush
# Notes.: command executed once to flush IPS, by shutdown (resp. by stop of the jail or this action)
# Values: CMD
#
actionflush = <pfctl> -t <tablename>-<name> -T flush
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck = <pfctl> -sr | grep -q <tablename>-<name>
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: <ip> IP address
# <failures> number of failures
# <time> unix timestamp of the ban time
# Values: CMD
#
actionban = <pfctl> -t <tablename>-<name> -T add <ip>
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: <ip> IP address
# <failures> number of failures
# <time> unix timestamp of the ban time
# Values: CMD
#
# note -r option used to remove matching rule
actionunban = <pfctl> -t <tablename>-<name> -T delete <ip>
# Option: pfctl
#
# Use anchor as jailname to manipulate affected rulesets only.
# If more parameter expected it can be extended with `pf[pfctl="<known/pfctl> ..."]`
#
pfctl = pfctl -a f2b/<name>
[Init]
# Option: tablename
# Notes.: The pf table name.
# Values: [ STRING ]
#
tablename = f2b
# Option: block
#
# The action you want pf to take.
# Probably, you want "block quick", but adjust as needed.
# If you want to log all blocked use "blog log quick"
block = block quick
# Option: protocol
# Notes.: internally used by config reader for interpolations.
# Values: [ tcp | udp | icmp | ipv6-icmp ] Default: tcp
#
protocol = tcp
# Option: actiontype
# Notes.: defines additions to the blocking rule
# Values: leave empty to block all attempts from the host
# Default: Value of the multiport
actiontype = <multiport>
# Option: allports
# Notes.: default addition to block all ports
# Usage.: use in jail config: "banaction = pf[actiontype=<allports>]"
allports = any
# Option: multiport
# Notes.: addition to block access only to specific ports
# Usage.: use in jail config: "banaction = pf[actiontype=<multiport>]"
multiport = any port $port

View File

@@ -0,0 +1,29 @@
# Fail2Ban configuration file
#
# Author: Michael Gebetsroither
#
# This is for blocking whole hosts through blackhole routes.
#
# PRO:
# - Works on all kernel versions and as no compatibility problems (back to debian lenny and WAY further).
# - It's FAST for very large numbers of blocked ips.
# - It's FAST because it Blocks traffic before it enters common iptables chains used for filtering.
# - It's per host, ideal as action against ssh password bruteforcing to block further attack attempts.
# - No additional software required beside iproute/iproute2
#
# CON:
# - Blocking is per IP and NOT per service, but ideal as action against ssh password bruteforcing hosts
[Definition]
actionban = ip route add <blocktype> <ip>
actionunban = ip route del <blocktype> <ip>
actioncheck =
actionstart =
actionstop =
[Init]
# Option: blocktype
# Note: Type can be blackhole, unreachable and prohibit. Unreachable and prohibit correspond to the ICMP reject messages.
# Values: STRING
blocktype = unreachable

View File

@@ -0,0 +1,99 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
#
[INCLUDES]
before = sendmail-common.conf
[Definition]
# bypass ban/unban for restored tickets
norestored = 1
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart = printf %%b "Subject: [Fail2Ban] <name>: started on <fq-hostname>
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The jail <name> has been started successfully.\n
Output will be buffered until <lines> lines are available.\n
Regards,\n
Fail2Ban" | <mailcmd>
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop = if [ -f <tmpfile> ]; then
printf %%b "Subject: [Fail2Ban] <name>: summary from <fq-hostname>
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
These hosts have been banned by Fail2Ban.\n
`cat <tmpfile>`
Regards,\n
Fail2Ban" | <mailcmd>
rm <tmpfile>
fi
printf %%b "Subject: [Fail2Ban] <name>: stopped on <fq-hostname>
From: Fail2Ban <<sender>>
To: <dest>\n
Hi,\n
The jail <name> has been stopped.\n
Regards,\n
Fail2Ban" | <mailcmd>
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = printf %%b "`date`: <ip> (<failures> failures)\n" >> <tmpfile>
LINE=$( wc -l <tmpfile> | awk '{ print $1 }' )
if [ $LINE -ge <lines> ]; then
printf %%b "Subject: [Fail2Ban] <name>: summary from <fq-hostname>
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
These hosts have been banned by Fail2Ban.\n
`cat <tmpfile>`
Regards,\n
Fail2Ban" | <mailcmd>
rm <tmpfile>
fi
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban =
[Init]
# Default name of the chain
#
name = default
# Default number of lines that are buffered
#
lines = 5
# Default temporary file
#
tmpfile = /var/run/fail2ban/tmp-mail.txt

View File

@@ -0,0 +1,77 @@
# Fail2Ban configuration file
#
# Common settings for sendmail actions
#
# Users can override the defaults in sendmail-common.local
[INCLUDES]
after = sendmail-common.local
[Definition]
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart = printf %%b "Subject: [Fail2Ban] <name>: started on <fq-hostname>
Date: `LC_ALL=C date +"%%a, %%d %%h %%Y %%T %%z"`
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The jail <name> has been started successfully.\n
Regards,\n
Fail2Ban" | <mailcmd>
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop = printf %%b "Subject: [Fail2Ban] <name>: stopped on <fq-hostname>
Date: `LC_ALL=C date +"%%a, %%d %%h %%Y %%T %%z"`
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The jail <name> has been stopped.\n
Regards,\n
Fail2Ban" | <mailcmd>
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban =
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban =
[Init]
# Your system mail command
#
mailcmd = /usr/sbin/sendmail -f "<sender>" "<dest>"
# Recipient mail address
#
dest = root
# Sender mail address
#
sender = fail2ban
# Sender display name
#
sendername = Fail2Ban

View File

@@ -0,0 +1,59 @@
# Fail2Ban configuration file
#
# Author: Viktor Szépe
#
#
[INCLUDES]
before = sendmail-common.conf
helpers-common.conf
[Definition]
# bypass ban/unban for restored tickets
norestored = 1
# Option: actionban
# Notes.: Command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# You need to install geoiplookup and the GeoLite or GeoIP databases.
# (geoip-bin and geoip-database in Debian)
# The host command comes from bind9-host package.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = ( printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from <fq-hostname>
Date: `LC_ALL=C date +"%%a, %%d %%h %%Y %%T %%z"`
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The IP <ip> has just been banned by Fail2Ban after
<failures> attempts against <name>.\n\n
Here is more information about <ip> :\n
http://bgp.he.net/ip/<ip>
http://www.projecthoneypot.org/ip_<ip>
http://whois.domaintools.com/<ip>\n\n
Country:`geoiplookup -f /usr/share/GeoIP/GeoIP.dat "<ip>" | cut -d':' -f2-`
AS:`geoiplookup -f /usr/share/GeoIP/GeoIPASNum.dat "<ip>" | cut -d':' -f2-`
hostname: <ip-host>\n\n
Lines containing failures of <ip> (max <grepmax>)\n";
%(_grep_logs)s;
printf %%b "\n
Regards,\n
Fail2Ban" ) | <mailcmd>
[Init]
# Default name of the chain
#
name = default
# Path to the log files which contain relevant lines for the abuser IP
#
logpath = /dev/null
# Number of log lines to include in the email
#
#grepmax = 1000
#grepopts = -m <grepmax>

View File

@@ -0,0 +1,41 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
#
[INCLUDES]
before = sendmail-common.conf
mail-whois-common.conf
[Definition]
# bypass ban/unban for restored tickets
norestored = 1
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from <fq-hostname>
Date: `LC_ALL=C date +"%%a, %%d %%h %%Y %%T %%z"`
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The IP <ip> has just been banned by Fail2Ban after
<failures> attempts against <name>.\n\n
Here is more information about <ip> :\n
`%(_whois_command)s`\n\n
Matches for <name> with <ipjailfailures> failures IP:<ip>\n
<ipjailmatches>\n\n
Regards,\n
Fail2Ban" | <mailcmd>
[Init]
# Default name of the chain
#
name = default

View File

@@ -0,0 +1,41 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
#
[INCLUDES]
before = sendmail-common.conf
mail-whois-common.conf
[Definition]
# bypass ban/unban for restored tickets
norestored = 1
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from <fq-hostname>
Date: `LC_ALL=C date +"%%a, %%d %%h %%Y %%T %%z"`
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The IP <ip> has just been banned by Fail2Ban after
<failures> attempts against <name>.\n\n
Here is more information about <ip> :\n
`%(_whois_command)s`\n\n
Matches with <ipfailures> failures IP:<ip>\n
<ipmatches>\n\n
Regards,\n
Fail2Ban" | <mailcmd>
[Init]
# Default name of the chain
#
name = default

View File

@@ -0,0 +1,52 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
#
[INCLUDES]
before = sendmail-common.conf
mail-whois-common.conf
helpers-common.conf
[Definition]
# bypass ban/unban for restored tickets
norestored = 1
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = ( printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from <fq-hostname>
Date: `LC_ALL=C date +"%%a, %%d %%h %%Y %%T %%z"`
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The IP <ip> has just been banned by Fail2Ban after
<failures> attempts against <name>.\n\n
Here is more information about <ip> :\n"
%(_whois_command)s;
printf %%b "\nLines containing failures of <ip> (max <grepmax>)\n";
%(_grep_logs)s;
printf %%b "\n
Regards,\n
Fail2Ban" ) | <mailcmd>
[Init]
# Default name of the chain
#
name = default
# Path to the log files which contain relevant lines for the abuser IP
#
logpath = /dev/null
# Number of log lines to include in the email
#
#grepmax = 1000
#grepopts = -m <grepmax>

View File

@@ -0,0 +1,41 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
#
[INCLUDES]
before = sendmail-common.conf
mail-whois-common.conf
[Definition]
# bypass ban/unban for restored tickets
norestored = 1
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from <fq-hostname>
Date: `LC_ALL=C date +"%%a, %%d %%h %%Y %%T %%z"`
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The IP <ip> has just been banned by Fail2Ban after
<failures> attempts against <name>.\n\n
Here is more information about <ip> :\n
`%(_whois_command)s`\n\n
Matches:\n
<matches>\n\n
Regards,\n
Fail2Ban" | <mailcmd>
[Init]
# Default name of the chain
#
name = default

View File

@@ -0,0 +1,40 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
#
[INCLUDES]
before = sendmail-common.conf
mail-whois-common.conf
[Definition]
# bypass ban/unban for restored tickets
norestored = 1
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from <fq-hostname>
Date: `LC_ALL=C date +"%%a, %%d %%h %%Y %%T %%z"`
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The IP <ip> has just been banned by Fail2Ban after
<failures> attempts against <name>.\n\n
Here is more information about <ip> :\n
`%(_whois_command)s`\n
Regards,\n
Fail2Ban" | <mailcmd>
[Init]
# Default name of the chain
#
name = default

View File

@@ -0,0 +1,37 @@
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
#
#
[INCLUDES]
before = sendmail-common.conf
[Definition]
# bypass ban/unban for restored tickets
norestored = 1
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = printf %%b "Subject: [Fail2Ban] <name>: banned <ip> from <fq-hostname>
Date: `LC_ALL=C date +"%%a, %%d %%h %%Y %%T %%z"`
From: <sendername> <<sender>>
To: <dest>\n
Hi,\n
The IP <ip> has just been banned by Fail2Ban after
<failures> attempts against <name>.\n
Regards,\n
Fail2Ban" | <mailcmd>
[Init]
# Default name of the chain
#
name = default

View File

@@ -0,0 +1,106 @@
# Fail2Ban configuration file
#
# Author: Eduardo Diaz
#
# This is for ipset protocol 6 (and hopefully later) (ipset v6.14).
# for shorewall
#
# Use this setting in jail.conf to modify use this action instead of a
# default one
#
# banaction = shorewall-ipset-proto6
#
# This requires the program ipset which is normally in package called ipset.
#
# IPset was a feature introduced in the linux kernel 2.6.39 and 3.0.0
# kernels, and you need Shorewall >= 4.5.5 to use this action.
#
# The default Shorewall configuration is with "BLACKLISTNEWONLY=Yes" (see
# file /etc/shorewall/shorewall.conf). This means that when Fail2ban adds a
# new shorewall rule to ban an IP address, that rule will affect only new
# connections. So if the attacker goes on trying using the same connection
# he could even log in. In order to get the same behavior of the iptable
# action (so that the ban is immediate) the /etc/shorewall/shorewall.conf
# file should me modified with "BLACKLISTNEWONLY=No".
#
#
# Enable shorewall to use a blacklist using iptables creating a file
# /etc/shorewall/blrules and adding "DROP net:+f2b-ssh all" and
# similar lines for every jail. To enable restoring you ipset you
# must set SAVE_IPSETS=Yes in shorewall.conf . You can read more
# about ipsets handling in Shorewall at http://shorewall.net/ipsets.html
#
# To force creation of the ipset in the case that somebody deletes the
# ipset create a file /etc/shorewall/initdone and add one line for
# every ipset (this files are in Perl) and add 1 at the end of the file.
# The example:
# system("/usr/sbin/ipset -quiet -exist create f2b-ssh hash:ip timeout 600 ");
# 1;
#
# To destroy the ipset in shorewall you must add to the file /etc/shorewall/stopped
# # One line of every ipset
# system("/usr/sbin/ipset -quiet destroy f2b-ssh ");
# 1; # This must go to the end of the file if not shorewall compilation fails
#
[Definition]
# Option: actionstart
# Notes.: command executed on demand at the first ban (or at the start of Fail2Ban if actionstart_on_demand is set to false).
# Values: CMD
#
actionstart = if ! ipset -quiet -name list f2b-<name> >/dev/null;
then ipset -quiet -exist create f2b-<name> <ipsettype> timeout <default-ipsettime> maxelem <maxelem>;
fi
# Option: actionstop
# Notes.: command executed at the stop of jail (or at the end of Fail2Ban)
# Values: CMD
#
actionstop = ipset flush f2b-<name>
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = ipset add f2b-<name> <ip> timeout <ipsettime> -exist
# actionprolong = %(actionban)s
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban = ipset del f2b-<name> <ip> -exist
# Option: default-ipsettime
# Notes: specifies default timeout in seconds (handled default ipset timeout only)
# Values: [ NUM ] Default: 0 (no timeout, managed by fail2ban by unban)
default-ipsettime = 0
# Option: ipsettime
# Notes: specifies ticket timeout (handled ipset timeout only)
# Values: [ NUM ] Default: 0 (managed by fail2ban by unban)
ipsettime = 0
# expression to calculate timeout from bantime, example:
# banaction = %(known/banaction)s[ipsettime='<timeout-bantime>']
timeout-bantime = $([ "<bantime>" -le 2147483 ] && echo "<bantime>" || echo 0)
[Init]
# Option: ipsettype
# Notes: specifies type of set, see `man --pager='less -p "^SET TYPES"' ipset` for details
# Values: hash:ip, hash:net, etc... Default: hash:ip
ipsettype = hash:ip
# Option: maxelem
# Notes: maximal number of elements which can be stored in the ipset
# You may want to increase this for long-duration/high-volume jails
# Values: [ NUM ] Default: 65536
maxelem = 65536

Some files were not shown because too many files have changed in this diff Show More