Serwer nginx – minimalizowanie zbieranych danych w logach dostępu
Kończąc opisane dwa miesiące temu zmiany w polityce prywatności, skończyłem projekt usuwania zbędnych danych z logów dostępu nginxa. Opiszę pokrótce gotowy fragment pliku konfiguracyjnego serwera i pokażę, jak skonfigurować Promtaila, żeby przetwarzał logi w nowym formacie.
W nginxie dyrektywa access_log
(i często towarzysząca log_format
) mogą być zdefiniowane na poziomie bloku http
lub server
. W moim wypadku są to globalne ustawienia dla wszystkich wirtualnych hostów i wygląda następująco:
map $remote_addr $remote_addr_anon {
~(?P<ip>\d+\.\d+\.\d+)\. $ip.0;
~(?P<ip>[^:]+:[^:]+): $ip::;
127.0.0.1 $remote_addr;
::1 $remote_addr;
default 0.0.0.0;
}
map $http_x_forwarded_for $http_x_forwarded_for_anon {
~(?P<ip>\d+\.\d+\.\d+)\. $ip.0;
~(?P<ip>[^:]+:[^:]+): $ip::;
127.0.0.1 $http_x_forwarded_for;
::1 $http_x_forwarded_for;
default 0.0.0.0;
}
log_format main
'[$time_local] $http_host '
'$remote_addr_anon $http_x_forwarded_for_anon'
'"$request" $status $body_bytes_sent';
access_log /var/log/nginx/access.log main;
Format main
zawiera absolutne minimum informacji przydatnych dla utrzymania serwera. Są to kolejno:
- Czas requestu
- Nagłówek
Host
z żądania, co przydatne jest, jeśli mamy kilka wirtualnych hostów w jednym logu - Adresy IP zdalnego hosta i z nagłówka
X-Forwarded-For
, z których usunięto ostatni oktet - Metodę HTTP (np.
GET
,POST
), ścieżkę URL żądania oraz wersję protokołu (np.HTTP/1.1
) - Kod odpowiedzi
- Ilość przesłanych bajtów odpowiedzi
Usunięcie ostatniego oktetu realizowane jest przez dyrektywy map
. Gotowiec za:
https://chriswiegman.com/2019/09/anonymizing-nginx-logs/
Warto zwrócić uwagę, że względem standardowego formatu logów nginxa nie kolekcjonujemy zbędnych:
- Pełnych adresów IP
- Nagłówka
Referrer
, co uniemożliwia śledzenie skąd użytkownik do nas trafił - Nagłówka
User-Agent
co anonimizuje używaną przeglądarkę
Jeśli używamy Promtaila do przekazywania logów do centralnego serwera przyda nam się zaktualizowany plik konfiguracyjny do parsowania linii logów:
scrape_configs:
- job_name: nginx_access
static_configs:
- targets:
- localhost
labels:
hostname: "webserver.tld"
job: nginx_access
__path__: /var/log/nginx/access.log
pipeline_stages:
- match:
selector: '{job="nginx_access"}'
stages:
- regex:
expression: '^\[(?P<time_local>.*)\] (?P<http_host>[^ ]*) (?P<remote_addr_anon>[^ ]*) (?P<http_x_forwarded_for_anon>[^ ]*) "(?P<method>[^ ]*) (?P<request>[^ ]*) (?P<proto>[^ ]*)" (?P<status>[\d]+) (?P<body_bytes_sent>[\d]+)'
- labels:
http_host:
method:
status:
Efektem zbierania logów przez Promtaila są takie oto dane widoczne w Loki: