Grafana-banner

Nginx Proxy Managerin GeoBlock-liikenteen visualisointi Grafanalla (Loki & Promtail)

Nginx Proxy Managerin GeoBlock-liikenteen visualisointi Grafanalla (Loki & Promtail)

Aiemmassa oppaassa kävimme läpi, kuinka asettaa Nginx Proxy Manageriin (NPM) GeoBlocking MaxMindin tietokannan avulla. Se on tehokas tapa estää ei-toivottu liikenne tietyistä maista ja palauttaa niille esimerkiksi kustomoitu 503-virhesivu.

Mutta mistä tiedämme, kuinka paljon liikennettä oikeasti blokataan ja mistä maista sitä tulee? Tässä oppaassa rakennamme seurantapaneelin Grafanan, Lokin ja Promtailin avulla. Näytän, kuinka NPM:n lokit muutetaan JSON-muotoon, lähetetään Lokille ja visualisoidaan upeaksi maailmankartaksi ja top-listaksi.

Vaihe 1: Nginx-lokien muuttaminen JSON-muotoon

Oletuksena Nginx kirjoittaa lokia pelkkänä tekstinä. Jotta Grafana voi suodattaa dataa kätevästi (esimerkiksi maatunnuksen tai eston perusteella), meidän täytyy kertoa Nginxille, että haluamme lokit rakenteellisena JSON-datana.

Avaa aiemmin luomasi Nginxin lisäkonfiguraatiotiedosto (esim. /docker/npm/data/nginx/custom/http_top.conf) ja päivitä se tähän muotoon:

charset utf-8;

geoip2 /data/geoip2/GeoLite2-City.mmdb {
    auto_reload 3h;
    $geoip2_metadata_country_build metadata build_epoch;
    $geoip2_data_country_code default=XX source=$remote_addr country iso_code;
    
    # HUOM: Käytä ehdottomasti "en" (englanti), jotta MaxMind palauttaa maan koko nimen luotettavasti. 
    # Jos käytät "fi", moni maa palauttaa pelkän viivan (-).
    $geoip2_data_country_name default=- country names en;
    $geoip2_data_city_name default=- city names en;
    $geoip2_data_region_name default=- subdivisions 0 names en;
}

geo $allowed_ip {
    default no;             # Blokataan kaikki oletuksena
    10.10.0.0/24 yes;     # Whitelist: Oma lähiverkko
}

map $geoip2_data_country_code $allowed_country {
    default $allowed_ip;
    DE yes;                 # Whitelist: Vain Saksa sallittu
}

# Grafanaa varten räätälöity JSON-loki
log_format json_analytics escape=json '{'
  '"time_local": "$time_local", '
  '"remote_addr": "$remote_addr", '
  '"request_uri": "$request_uri", '
  '"status": "$status", '
  '"server_name": "$server_name", '
  '"request_method": "$request_method", '
  '"country_code": "$geoip2_data_country_code", '
  '"country_name": "$geoip2_data_country_name", '
  '"city_name": "$geoip2_data_city_name", '
  '"is_allowed": "$allowed_country" '
'}';

Muista myös varmistaa, että kyseistä json_analytics -muotoa käytetään Nginxin access-lokeissa (esim. server_proxy.conf tiedostossa):

access_log /data/logs/all_proxy_access.log json_analytics;
error_log /data/logs/all_proxy_error.log warn;

Lataa Nginx uudelleen: docker exec -it npm-containerin-nimi nginx -s reload

Nimen näet docker ps komennolla.

Vaihe 2: Valmistele Grafana-ympäristön kansiot

Luodaan seurantatyökaluille oma hakemisto. Nykyiset Docker-imaget vaativat tiukat kansion omistajuudet turvallisuussyistä.

mkdir -p /docker/grafana
cd /docker/grafana

# Luodaan tarvittavat alikansiot
mkdir -p config-loki config-promtail loki-data grafana-data

# Asetetaan oikeudet, jotta containerit voivat tallentaa dataa
sudo chown -R 10001:10001 loki-data
sudo chown -R 472:472 grafana-data

Vaihe 3: Konfiguraatiotiedostot Promtailille ja Lokille

Promtail lukee NPM:n lokitiedostoja ja lähettää ne Lokille, joka indeksoi ne Grafanaa varten.

Luo tiedosto config-promtail/config.yaml:

server:
  http_listen_port: 9080
  grpc_listen_port: 0
positions:
  filename: /tmp/positions.yaml
clients:
  - url: http://loki:3100/loki/api/v1/push
scrape_configs:
  - job_name: system
    static_configs:
      - targets:
          - localhost
        labels:
          job: varlogs
          __path__: /var/log/*log

Luo tiedosto config-loki/local-config.yaml

auth_enabled: false
server:
  http_listen_port: 3100
common:
  path_prefix: /loki
  storage:
    filesystem:
      chunks_directory: /loki/chunks
      rules_directory: /loki/rules
  replication_factor: 1
  ring:
    kvstore:
      store: inmemory
schema_config:
  configs:
    - from: 2020-10-24
      store: boltdb-shipper
      object_store: filesystem
      schema: v11
      index:
        prefix: index_
        period: 24h

Vaihe 4: Docker Compose

Luo tiedosto compose.yaml /docker/grafana/ -kansioon.Huom: Varmista, että Promtailin volume viittaa oikeaan paikkaan isäntäkoneellasi, jossa Nginx Proxy Managerin lokit sijaitsevat.

services:
  loki:
    image: grafana/loki:latest
    ports:
      - "3100:3100"
    command: -config.file=/etc/loki/local-config.yaml
    volumes:
      - ./loki-data:/loki
      - ./config-loki:/etc/loki
    restart: unless-stopped

  promtail:
    image: grafana/promtail:latest
    volumes:
      # MUUTA TÄMÄ vastaamaan omaa NPM asennustasi:
      - /docker/npm/data/logs:/var/log 
      - ./config-promtail/config.yaml:/etc/promtail/config.yaml
    restart: unless-stopped

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    environment:
      - GF_AUTH_ANONYMOUS_ENABLED=false
    volumes:
      - ./grafana-data:/var/lib/grafana
    restart: unless-stopped

Käynnistä ympäristö: docker compose up -d

Vaihe 5: Grafana Dashboardin rakentaminen

Kirjaudu Grafanaan osoitteessa http://palvelimen-ip:3000 (oletustunnukset: admin / admin). Lisää ensin tietolähde (Data Source): Valitse Loki ja aseta URL-osoitteeksi http://loki:3100.

Luo uusi Dashboard ja lisää siihen kaksi paneelia:

1. Maailmankartta (Geomap) – Näyttää estetyt yhteydet kartalla

Valitse paneelin tyypiksi Geomap (tai Heatmap) ja aseta kyselyksi (LogQL):

sum by (country_code) (
  count_over_time({job="varlogs", filename=~".*access.*"} | json | __error__="" | is_allowed="no" | status="503" | country_code != "XX" | country_code != "" [$__range])
)

Miksi nämä filtterit?

  • filename=~".*access.*" ohittaa Nginxin virhelokit (error.log), jotka ovat puhdasta tekstiä ja rikkovat JSON-parserin.

  • $__range skaalautuu Grafanan aikavalitsimen mukaan.

  • is_allowed="no" ja status="503" poimivat vain oikeasti estetyt yhteydet.

Tärkeät asetukset kartalle (Transform data & Map Layers): Jotta kartta ymmärtää datan oikein, sinun on tehtävä kaksi asiaa:

  1. Mene Transform data -välilehdelle ja lisää: Merge (laita tämä aivan ylimmäksi!) ja sen alle Labels to fields.

  2. Oikean reunan asetuksista valitse Map layers -> Data layer:

    • Location mode: Lookup

    • Lookup field: country_code

    • Gazetteer: Countries

    • Size / Weight field: Value

2. Estetyt maat Top-lista (Bar Gauge)

Lisää toinen paneeli, tyypiltään Bar Gauge, ja aseta kyselyksi:

sum by (country_name) (
  count_over_time({job="varlogs", filename=~".*access.*"} | json | __error__="" | is_allowed="no" | status="503" | country_name != "-" [$__range])
) or vector(0)

Tässä or vector(0) on tärkeä varmistus: jos liikennettä ei ole hetkeen blokattu, Grafana ei kaadu ”No Data” -virheeseen, vaan palauttaa siististi arvon 0.

Siisti asettelu (Transform data): Päästäksesi eroon rumasta Value #A -tekstistä, joka syntyy vector(0) -toiminnosta, käytä jälleen transformaatioita:

  1. Mene Transform data -välilehdelle.

  2. Lisää Labels to fields.

  3. Lisää Filter data by values:

    • Type: Include / Match: All

    • Conditions: Field -> Value -> Is greater than -> 0. Tämä piilottaa automaattisesti tyhjät rivit, ja jäljelle jää vain siisti lista estettyjen maiden oikeista nimistä.

Ongelmanratkaisu: Jos kartta ei näy tai lataudu

Joskus Grafanan oletusarvoinen taustakartta ei lataudu oikein verkkorajoitusten tai palvelinongelmien vuoksi, jolloin kartan tilalla näkyy vain tyhjä ruutu. Voit korjata tämän vaihtamalla taustakartaksi vaihtoehtoisen palvelimen, kuten Carton tyylikkään tumman teeman (dark_all).

Näin vaihdat taustakartan:

  1. Paina ”Traffic Map” -paneelin otsikkoa ja valitse Edit.

  2. Etsi oikean reunan valikosta osio Map layers ja avaa Basemap layer -asetukset.

  3. Määritä asetukset seuraavasti:

    • Layer type: arcGIS MapServer

    • Server instance: Custom MapServer

    • URL Template: [https://basemaps.cartocdn.com/rastertiles/dark_all/](https://basemaps.cartocdn.com/rastertiles/dark_all/){z}/{x}/{y}.png(Huom: Mikäli käytät Carton rekisteröityä tiliä, voit lisätä osoitteen perään ?key={YOUR_API_KEY}, mutta julkiset peruskartat toimivat usein myös ilman avainta).

    • Attribution: © Carto.com

  4. Paina ylhäältä Apply ja tallenna Dashboard. Kartan pitäisi nyt ilmestyä näkyviin välittömästi.

(Vinkki: Jos haluat kokeilla karttaan muita väriteemoja, löydät kaikki tuetut tyylit suoraan Carton GitHub-repositoriosta.)

Yhteenveto

Nyt sinulla on täysin lokaalisti pyörivä, visuaalinen seurantataulu palvelimesi GeoBlock-osumille. Nginx puskee dataa JSON-muodossa, Promtail poimii sen, Loki indeksoi, ja Grafana piirtää sen kauniisti kartalle ilman minkäänlaisia ulkoisia pilvipalveluita tai API-avaimia.