{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://jp1337.github.io/easywall/schemas/easywall.schema.json",
  "title": "easywall core configuration",
  "description": "Configuration for the easywall-core daemon. See https://jp1337.github.io/easywall/configuration",
  "type": "object",
  "additionalProperties": false,
  "required": ["socket_path", "data_dir", "log_dir"],
  "properties": {
    "socket_path": {
      "type": "string",
      "description": "Path to the Unix socket shared between easywall-core and easywall-web.",
      "default": "/run/easywall/core.sock",
      "examples": ["/run/easywall/core.sock"]
    },
    "data_dir": {
      "type": "string",
      "description": "Directory for persistent data (rules.json, version cache). Must be writable by root.",
      "default": "/var/lib/easywall",
      "examples": ["/var/lib/easywall"]
    },
    "log_dir": {
      "type": "string",
      "description": "Directory for log files (audit.log). Must be writable by root.",
      "default": "/var/log/easywall",
      "examples": ["/var/log/easywall"]
    },
    "acceptance": {
      "type": "object",
      "description": "Two-step activation settings. After applying rules, easywall waits for confirmation before committing. If not confirmed, rules are rolled back.",
      "additionalProperties": false,
      "properties": {
        "enabled": {
          "type": "boolean",
          "description": "Enable the two-step activation mechanism. Strongly recommended — prevents accidental lockouts.",
          "default": true
        },
        "duration": {
          "type": "integer",
          "description": "Seconds to wait for confirmation before auto-rollback.",
          "minimum": 10,
          "maximum": 3600,
          "default": 120,
          "examples": [60, 120, 300]
        }
      }
    },
    "ipv6": {
      "type": "object",
      "description": "IPv6 support settings.",
      "additionalProperties": false,
      "properties": {
        "enabled": {
          "type": "boolean",
          "description": "Enable IPv6 firewall rules. Requires kernel IPv6 support.",
          "default": true
        },
        "icmp_allow_router_advertisement": {
          "type": "boolean",
          "description": "Allow ICMPv6 Router Advertisement messages (type 134). Required for SLAAC address assignment.",
          "default": true
        },
        "icmp_allow_neighbor_advertisement": {
          "type": "boolean",
          "description": "Allow ICMPv6 Neighbor Advertisement/Solicitation (types 135/136). Required for IPv6 address resolution.",
          "default": true
        }
      }
    },
    "docker": {
      "type": "object",
      "description": "Docker coexistence settings. easywall uses its own nftables table (inet easywall) and does not touch Docker's chains.",
      "additionalProperties": false,
      "properties": {
        "enabled": {
          "type": "boolean",
          "description": "Auto-detect Docker bridge interfaces and whitelist their networks.",
          "default": false
        },
        "allow_bridge_networks": {
          "type": "boolean",
          "description": "Automatically add ACCEPT rules for detected Docker bridge networks.",
          "default": true
        },
        "custom_networks": {
          "type": "array",
          "description": "Additional networks to whitelist (CIDR notation). Useful for custom Docker networks not auto-detected.",
          "items": {
            "type": "string",
            "pattern": "^(\\d{1,3}\\.){3}\\d{1,3}/\\d{1,2}$|^[0-9a-fA-F:]+/\\d{1,3}$",
            "examples": ["172.20.0.0/16", "192.168.100.0/24"]
          },
          "default": []
        }
      }
    },
    "firewall": {
      "type": "object",
      "description": "Protection modules. All filters are applied via nftables directly — no subprocess, no injection risk.",
      "additionalProperties": false,
      "properties": {
        "ssh_brute_force": {
          "type": "boolean",
          "description": "Enable SSH brute-force prevention. Limits concurrent connections per source IP to ssh_brute_force_connection_limit.",
          "default": true
        },
        "ssh_brute_force_log": {
          "type": "boolean",
          "description": "Log dropped SSH brute-force packets.",
          "default": false
        },
        "ssh_brute_force_connection_limit": {
          "type": "integer",
          "description": "Maximum concurrent SSH connections per source IP before blocking.",
          "minimum": 1,
          "maximum": 100,
          "default": 5
        },
        "ssh_brute_force_log_limit": {
          "type": "integer",
          "description": "Maximum log entries per minute for SSH brute-force drops.",
          "minimum": 1,
          "default": 60
        },
        "icmp_flood": {
          "type": "boolean",
          "description": "Enable ICMP flood prevention. Rate-limits ICMP packets per source IP.",
          "default": true
        },
        "icmp_flood_log": {
          "type": "boolean",
          "description": "Log dropped ICMP flood packets.",
          "default": false
        },
        "icmp_flood_connection_limit": {
          "type": "integer",
          "description": "Maximum ICMP packets per second per source IP.",
          "minimum": 1,
          "maximum": 1000,
          "default": 10
        },
        "icmp_flood_log_limit": {
          "type": "integer",
          "description": "Maximum log entries per minute for ICMP flood drops.",
          "minimum": 1,
          "default": 60
        },
        "syn_flood": {
          "type": "boolean",
          "description": "Enable SYN flood prevention. Rate-limits new TCP SYN packets per source IP.",
          "default": true
        },
        "syn_flood_log": {
          "type": "boolean",
          "description": "Log dropped SYN flood packets.",
          "default": false
        },
        "syn_flood_limit": {
          "type": "integer",
          "description": "Maximum new TCP connections per second per source IP before rate-limiting.",
          "minimum": 1,
          "maximum": 10000,
          "default": 100
        },
        "port_scan": {
          "type": "boolean",
          "description": "Enable port scan detection. Drops NULL, FIN, XMAS, and other scan probe packets.",
          "default": true
        },
        "port_scan_log": {
          "type": "boolean",
          "description": "Log detected port scan packets.",
          "default": false
        },
        "drop_invalid_packets": {
          "type": "boolean",
          "description": "Drop packets in an invalid connection tracking state (ct state invalid).",
          "default": true
        },
        "drop_invalid_packets_log": {
          "type": "boolean",
          "description": "Log dropped invalid packets.",
          "default": false
        },
        "drop_fragments": {
          "type": "boolean",
          "description": "Drop IP-fragmented packets. May break legitimate large-MTU traffic.",
          "default": false
        },
        "drop_fragments_log": {
          "type": "boolean",
          "description": "Log dropped fragmented packets.",
          "default": false
        },
        "bogon_filter": {
          "type": "boolean",
          "description": "Drop packets from RFC-1918 private addresses arriving on external interfaces (bogon filter).",
          "default": false
        },
        "bogon_filter_log": {
          "type": "boolean",
          "description": "Log dropped bogon packets.",
          "default": false
        },
        "connection_limit_per_ip": {
          "type": "boolean",
          "description": "Limit maximum simultaneous connections per source IP.",
          "default": false
        },
        "connection_limit_max": {
          "type": "integer",
          "description": "Maximum simultaneous connections allowed per source IP.",
          "minimum": 1,
          "maximum": 100000,
          "default": 100
        },
        "tcp_rst_flood": {
          "type": "boolean",
          "description": "Enable TCP RST flood prevention. Rate-limits RST packets per source IP.",
          "default": false
        },
        "tcp_rst_flood_log": {
          "type": "boolean",
          "description": "Log dropped TCP RST flood packets.",
          "default": false
        },
        "tcp_rst_flood_limit": {
          "type": "integer",
          "description": "Maximum TCP RST packets per second per source IP.",
          "minimum": 1,
          "maximum": 10000,
          "default": 100
        },
        "drop_broadcast": {
          "type": "boolean",
          "description": "Drop broadcast packets (pkttype broadcast).",
          "default": false
        },
        "drop_multicast": {
          "type": "boolean",
          "description": "Drop multicast packets (pkttype multicast).",
          "default": false
        },
        "drop_anycast": {
          "type": "boolean",
          "description": "Drop anycast packets (pkttype anycast).",
          "default": false
        },
        "log_blocked_connections": {
          "type": "boolean",
          "description": "Log all packets dropped by the final DROP policy.",
          "default": false
        },
        "log_blocked_connections_limit": {
          "type": "integer",
          "description": "Maximum log entries per minute for general blocked connections.",
          "minimum": 1,
          "default": 60
        },
        "log_blacklist_connections": {
          "type": "boolean",
          "description": "Log packets dropped by the IP blacklist.",
          "default": false
        },
        "log_blacklist_connections_limit": {
          "type": "integer",
          "description": "Maximum log entries per minute for blacklisted connections.",
          "minimum": 1,
          "default": 60
        }
      }
    }
  }
}
