Oletushostin piilottaminen maailmalta Ngxillä

Logeissa näkyy usein tämän kaltaista roskaa:

167.94.138.189 - - [28/May/2025:13:31:24 +0300] "GET /favicon.ico HTTP/1.1" 404 146 "-" "Mozilla/5.0 (compatible; CensysInspect/1.1; +https://about.censys.io/)"

Toinen paljon kolkuteltu on GET ”/.env”, juuri, favicon tai robots.txt. Jos harrastaa suodatusta user-agentin perusteella, niin nuo eivät jää koskaan kiinni. Syy on se, että oletus-hostia ei ole määritelty, jolloin Nginx lähettää kaikki pyynnöt konffattujen domainien aakkosten ensimmäiselle. Varmuustoimi, että jotain vastataan. Mutta koska pyyntö tulee ilman hostia, ja useimmiten suodatukset on määritelty siellä, niin user-agenttiin tai geoip- tunnistukseen perustuvat filtteröinnit tipahtavat aina pois pelistä. Ja kaikki tulee läpi.

Tai sitten on pidetty Nginxin oletus päällä, ja se hyväksyy kaikki pyynnöt.

Tuo kaikki on roskaliikennettä. Kolkuttelua. Osa saattaa tokin olla väärin konfugroituja botteja, mutta koska ei tiedetä mille hostille ne olivat suuntaamassa, niin roskaa nekin ovat. Mutta ihmisiä ne eivät ole milloinkaan. Kukaan ei selaamistarkoituksessa suuntaa serverin IP-osoitteelle.

Ne kannattaa aina tappaa kuljeksimasta. Tappaminen tarkoittaa tässä tapauksessa Nginxin error 444, joka katkaisee hiljaisesti yhteyden, ja jättää botin tuhlaamaan aikaa. Samalla pidetään fail2ban laskemassa yrityksiä ja blokkaamaan IP-osoitteen esimerkiksi kahden yrityksen jälkeen. Minusta jo yksi yritys riittää, mutta makunsa kullakin. Tosin IP:n blokkaaminen on lähellä turhaa, koska botit vaihtavat sen aina muutaman yrityksen jälkeen, mutta aina se hieman hidastaa. Ja osa script kiddiestä kuitenkin operoi typeryyksissään omasta koti-IP:stä tai viiden taalan VPS:stä. Nuo pysähtyvät aina IP-banniin,

Oma osoite kannattaa kuitenkin whitelistata. Testejä tulee kuitenkin tehtyä.

Nginxin asettaminen

Nginx, ja myös Apache2, asettavat oletuskonffin. Itse en sitä käytä, koska haluan pitää sites-available/enable hakemistot puhtaina ylimääräisestä. Joten käytetään /etc/nginx/nginx.conf tiedostoa. Apache2 toimii samankaltaisesti, mutta syntaksi on eri — googleta.

Ensin tehdään pohjat, joita kutsutaan include avulla. Se on käytännössä hostin konffi, mutta pidetään se eri paikassa. Koska halutaan pysäyttää myös https-kutsut, niin tarvitaan SSL-sertifikaatti. Siinä ei voida käyttää Lets Encryptiä, joten tehdään dummy-sertifikaatti itse. Laadullahan ei ole merkitystä, koska nämä kaikki ovat de facto aina shellistä kommennettuja botteja, ja ne eivät TLS-kättelyä kuitenkaan tee ajatuksella, että itseallekirjoitettu häiritsisi. Ja jos häiritsee, niin kulku päättyy siihen.

Huomaa: itse toimin aina rootin roolissa, niin en käytä sudoa. Jos oma tapasi toimia on enemmän perinteinen, niin laita sudo paikalleen. Se tarvitaan suunnilleen joka komentoon.

Ensin tehdään hakemisto, jossa sertifikaatti säilytetään:

mkdir -p /etc/nginx/dummy-certs

Tehdään varsinainen SSL-sertifikaatti:

openssl req -x509 -nodes -days 3650 \
  -subj "/CN=invalid.local" \
  -newkey rsa:2048 \
  -keyout /etc/nginx/dummy-certs/dummy.key \
  -out /etc/nginx/dummy-certs/dummy.crt

Tuota ei tarvitse ihan joka välissä uusia. On voimassa 10 vuotta.

Nyt tarvitaan include tiedosto Nginxille. Hakemistovaihtoja on useampi, mutta itse käytän tämän tyyppisiin hakemisto /etc/nginx/global. Suuntaa sinne, tai jonnekin muualle.

Tarkoituksena on:

  • antaa error 444
  • olla kirjoittamatta ja sotkematta access.log
  • tehdä erillinen logi fail2ban käyttöön

Tehdään ensin konffi http-liikenteelle, eli portille 80.

nano reject_unknown_hosts_http.conf

Lisää tämä:

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;

    access_log off;

    error_log /var/log/nginx/fail2ban-invalid-host-http.log notice;

    return 444;
}

Sitten vastaava portista 443 saapuvalle https-liikenteelle:

nano reject_unknown_hosts_ssl.conf

Ja sinne tämä:

server {
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;
    server_name _;

    ssl_certificate     /etc/nginx/dummy-certs/dummy.crt;
    ssl_certificate_key /etc/nginx/dummy-certs/dummy.key;

    access_log off;

    error_log /var/log/nginx/fail2ban-invalid-host-https.log notice;

    return 444;
}

Syy siihen miksi noita ei laiteta samaan on se, että moinen eriyttäminen helpottaa mahdollista virheen etsimistä tai kohdennettua säätö. Ja ajatus myös on, että näihin ei tarvitse enää ikinä koskea.

Portin 80 liikennettä ei uudelleenohjata porttiin 443. Siinä ei olisi mitään mieltä. Kyseessä on roskaliikenne, jota halutaan palvella mahdollisimman vähän. Aivan riippumatta portista se pysäytetään niille jalansijoilleen.

Nuo täytyy vielä kertoa Nginxille.

nano /etc/nginx/nginx.conf

Lisää nämä rivit johonkin kohtaanhttp { lohkoa.

include /etc/nginx/global/reject_unknown_hosts_http.conf;
include /etc/nginx/global/reject_unknown_hosts_ssl.conf;

Sitten vakio temput nginx -t ja systemctl restart nginx ja ongelma on ratkaistu.

Fail2ban

Koska on aina hyvää politiikkaa hidastaa roskaajia, niin viedään tuo fail2banniin — varsinkin kun tarvittavat logit yksinkertaistettiin.

Tarvitaan jail:

nano /etc/fail2ban/jail.d/nginx-invalid-host.conf

Liitä ja aseta halusi mukaan.

[nginx-invalid-host-http]
enabled = true
port = http
filter = nginx-invalid-host
logpath = /var/log/nginx/fail2ban-invalid-host-http.log
maxretry = 2
findtime = 3600
bantime = 86400

[nginx-invalid-host-https]
enabled = true
port = https
filter = nginx-invalid-host
logpath = /var/log/nginx/fail2ban-invalid-host-https.log
maxretry = 2
findtime = 3600
bantime = 86400

Sitten vielä suodatin, että löydetään halutut asiat:

nano /etc/fail2ban/filter.d/nginx-invalid-host.conf

Näiden sääntöjen pitäisi sopia usemmiten, mutta jos alkaa tulla vääriä positiivisia, niin esimerkiksi laittamalla ehdon "server: _" tai ”no Host header” niin saat tarkemmaksi.

[Definition]
failregex = ^.*?:.*?:.*?:.*?client: <HOST>.*$

ignoreregex =

Login sijaintipaikka aiemmin kerrottiin, mutta ne on vielä luotava.

touch /var/log/nginx/fail2ban-invalid-host-{http,https}.log

Ja annetaan oikeudet — www-data:adm on tarkoituksella.

chown www-data:adm /var/log/nginx/fail2ban-invalid-host-*.log

Logrotate lienee paikallaan.

nano /etc/logrotate.d/nginx-fail2ban-invalid-host

Nämä säännöt taitavat olla aika yleispätevän sopivat.

/var/log/nginx/fail2ban-invalid-host-*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 640 www-data adm
    sharedscripts
    postrotate
        [ -s /run/nginx.pid ] && kill -USR1 `cat /run/nginx.pid`
    endscript
}

Fail2bannin säännöt täytyy ottaa käyttöön, ja jailien olemassaolo tarkistaa.

systemctl restart fail2ban
fail2ban-client status nginx-invalid-host-http
fail2ban-client status nginx-invalid-host-https

 

 

 

Jakke Lehtonen

Teen B2B-markkinoille sisällöntuottoa sekä UX-testauksia. Samaan liittyy myös koulutukset yrityksille ja webmaailman kanssa muutoin painiville. Serverien sielunelämää on joutunut ohessa opettelmaan. Toinen puoli toiminnasta on koirien ravitsemuksen ja ruokinnan suunnittelua sekä varsinkin omistajien kouluttamista hoitamaan koiriaan oikein ja vielä paremmin. Profiili: Jakke Lehtonen

Keskustele foorumilla Katiskan foorumi

WordPressin kommentit: