Warpage and fail2ban via vector

A working version to block intruderce into warpgate

compose.yml

services:
  warpgate:
    container_name: warpgate
    image: ghcr.io/warp-tech/warpgate
    ports:
      - 2222:2222
      - 127.0.0.1:8888:8888
    volumes:
      - ./data:/data:Z
      - ./sockets:/var/run
    stdin_open: true
    tty: true
    restart: always
    environment:
      - WARPGATE__WEB__TRUST_PROXY_HEADERS=true
    logging:
      driver: json-file
      options:
        max-size: "50m"
        max-file: "3"
  vector:
    image: timberio/vector:latest-alpine
    container_name: vector
    restart: unless-stopped
    depends_on:
      - warpgate
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./vector.yaml:/etc/vector/vector.yaml:ro
      - /var/log/warpgate:/var/log/warpgate
    command: ["--config", "/etc/vector/vector.yaml"]

vector.yaml

sources:
  warpgate:
    type: docker_logs
    include_containers:
      - warpgate

transforms:
  to_fail2ban:
    type: remap
    inputs:
      - warpgate
    source: |
      raw = string!(.message)

      # ANSI Escape Codes entfernen (falls vorhanden)
      msg = replace(raw, r'\x1b\[[0-9;]*m', "")

      # --- 1) HTTP Login failed (401) ---
      is_http_fail =
        contains(msg, "WARN HTTP:") &&
        contains(msg, "/@warpgate/api/auth/login") &&
        contains(msg, "status=401") &&
        contains(msg, "client_ip")

      # --- 2) SSH Auth failed (Credentials/User/Password) ---
      # Beispiel von dir:
      # "ERROR SSH: Failed to verify credentials ... client_ip=::ffff:222.138.251.223"
      is_ssh_fail =
        contains(msg, "ERROR SSH:") &&
        contains(msg, "Failed to verify credentials") &&
        contains(msg, "client_ip")

      if !(is_http_fail || is_ssh_fail) {
        abort
      }

      # Zeitstempel robust
      ts = format_timestamp!(now(), "%Y-%m-%dT%H:%M:%SZ")

      # IP extrahieren
      parsed = parse_regex!(msg, r'client_ip\s*=\s*(?P[0-9a-fA-F\.:]+)')
      ip = parsed.ip


      # IPv4-mapped IPv6 (::ffff:1.2.3.4) normalisieren -> 1.2.3.4
      ip = replace(ip, r'^::ffff:', "")


      # Ausgabezeile für fail2ban (einheitlich)
      if is_http_fail {
        .message = ts + " warpgate login failed (http) ip=" + ip
      } else {
        .message = ts + " warpgate login failed (ssh) ip=" + ip
      }

sinks:
  fail2ban_file:
    type: file
    inputs:
      - to_fail2ban
    path: "/var/log/warpgate/auth.log"
    encoding:
      codec: text

/etc/fail2ban/filter.d/warpgate.conf

[Definition]
datepattern = ^%%Y-%%m-%%dT%%H:%%M:%%SZ
failregex   = ^.*warpgate login failed.* ip=\s*$
ignoreregex =

/etc/fail2ban/jail.d/warpgate.conf

[warpgate]
enabled  = true
filter   = warpgate
logpath  = /var/log/warpgate/auth.log

maxretry = 5
findtime = 300
bantime  = 900

banaction = iptables-docker-allports

/etc/fail2ban/action.d/iptables-docker-allports.conf

[Definition]

# IPv4
actionstart = iptables -N f2b- || true
              iptables -C DOCKER-USER -j f2b- || iptables -I DOCKER-USER -j f2b-
              iptables -A f2b- -j RETURN

actionstop = iptables -D DOCKER-USER -j f2b- || true
             iptables -F f2b- || true
             iptables -X f2b- || true

actioncheck = iptables -n -L DOCKER-USER | grep -q f2b-

actionban = iptables -I f2b- 1 -s  -j DROP

actionunban = iptables -D f2b- -s  -j DROP


# IPv6
actionstart += ip6tables -N f2b- || true
               ip6tables -C DOCKER-USER -j f2b- || ip6tables -I DOCKER-USER -j f2b-
               ip6tables -A f2b- -j RETURN

actionstop += ip6tables -D DOCKER-USER -j f2b- || true
              ip6tables -F f2b- || true
              ip6tables -X f2b- || true

actioncheck += ip6tables -n -L DOCKER-USER | grep -q f2b-

actionban += ip6tables -I f2b- 1 -s  -j DROP

actionunban += ip6tables -D f2b- -s  -j DROP

fail2ban-regex /var/log/warpgate/auth.log /etc/fail2ban/filter.d/warpgate.conf
systemctl restart fail2ban
fail2ban-client status warpgate

Posts Tagged warpgate

Archives by Month: