Barátok, sziasztok!
Számos módszer létezik, hogy otthonról csatlakozzunk a munkahelyhez az irodában. Az egyik lehetőség a Microsoft Remote Desktop Gateway használata. Ez egy RDP HTTP-n keresztül. Nem szeretném itt a RDGW beállításával foglalkozni, és nem akarom mérlegelni, hogy jó vagy rossz, tekintsük ezt az egyik távoli elérési eszköznek. Azt szeretném megvitatni, hogyan védhetjük meg az RDGW szerverünket a gonosz internettől. Amikor beállítottam az RDGW szerveremet, azonnal aggódni kezdtem a védelem miatt, különösen a jelszavak brute force támadása elleni védelem miatt. Meglepett, hogy nem találtam az interneten cikkeket arról, hogyan lehet ezt megtenni. Nos, ezt nekem kell megoldanom.
Magában az RDGW-nak nincsenek védelmi funkciói. Igen, ki lehet venni nyílt interfészen a nyílt hálózatba, és jól fog működni. De egy jó rendszergazda vagy IT biztonsági szakember számára ez szorongást okozhat. Ráadásul elkerülheti azt a helyzetet, amikor a figyelmetlen alkalmazott megjegyzi a vállalati fiókjának a jelszavát otthoni számítógépén, majd megváltoztatja a jelszavát.
Jó módja a belső források védelmének a külső környezettől, ha különböző proxykat, publikáló rendszereket és más WAF-okat alkalmazunk. Ne feledjük, hogy az RDGW végül is http, tehát adódik, hogy egy speciális megoldást helyezünk el a belső szerverek és az internet között.
Tudom, hogy léteznek fantasztikus F5, A10, Netscaler (ADC) rendszerek. Mint e rendszerek egyik adminisztrátora, elmondhatom, hogy a brute force támadások ellen is lehetséges védekezés ezen rendszereken. És igen, ezek a rendszerek emellett meg fognak védeni a különféle syn flood támadásoktól is.
De nem minden cég engedheti meg magának egy ilyen megoldás beszerzését (és egy ilyen rendszer adminisztrátorának megtalálását :), miközben a biztonságról gondoskodhat!
Teljesen lehetséges ingyenes verziónak a HAProxy telepítése egy ingyenes operációs rendszeren. Teszteltem a Debian 10-en, a stabil tárolóban a haproxy verziója 1.8.19. A 2.0.xx verziókat is teszteltem a teszt tárolóból.
A Debian beállítását hagyjuk ki a cikkből. Röviden: a nyílt interfészen zárjunk le mindent, kivéve a 443-as portot, a szürke interfészen pedig — a politikája szerint, például zárjunk le mindent, kivéve a 22-es portot. Csak azt nyissuk meg, ami a működéshez szükséges (például VRRP, a lebegő IP-hez).
Először beállítottam a haproxy-t SSL bridging módban (ez a http mód) és aktiváltam a naplózást, hogy megnézhessem, mi történik belül az RDP-n. Úgy mondanám, hogy belelátok a közepébe. Nos, az összes RDGateway beállítási cikkben megadott útvonal, a /RDWeb hiányzik. Amit ott találunk, az a /rpc/rpcproxy.dll és a /remoteDesktopGateway/. Ehhez nem használnak standard GET/POST kéréseket, saját kérési típust alkalmaznak: RDG_IN_DATA, RDG_OUT_DATA.
Nem sok, de legalább valami.
Tessék, teszteljünk.
Elindítom az mstsc-t, elmegyek a szerverre, a naplókban négy 401-es (unauthorized) hibát látok, majd megadom a felhasználónevet/jelszót és látom a 200-as választ.
Kikapcsolom, újra elindítom, a naplókban ugyanazokat a négy 401-es hibákat látom. Hibás felhasználónév/jelszó megadásakor újra négy 401-es hibát látok. Ez pontosan az, amit keresünk. Ezt fogjuk keresni.
Mivel a bejelentkezési URL-t nem sikerült meghatározni, és azt is, hogy a haproxy-ban hogyan vadászni a 401-es hibára, ezért minden 4xx hibát fogok figyelni (valójában nem vadászni, hanem számolni). Ez is megfelelő a feladat megoldásához.
A védelem lényege az lesz, hogy számolni fogjuk a 4xx hibák számát (a backend-en) egy adott időegység alatt, és ha ez a megadott határérték fölé emelkedik, akkor elutasítjuk (a frontend-en) az összes további kapcsolatot arról az IP-címről a megadott időtartam alatt.
Technikailag ez nem lesz védelem a jelszópróbálkozások ellen, ez egy védelem a 4xx hibák ellen. Például, ha gyakran kérjük egy nem létező URL-t (404), akkor a védelem is életbe lép.
A legegyszerűbb és működő módszer az, hogy a backend-en számolunk, és blokkolunk, ha valami felesleges megjelenik:
frontend fe_rdp_tsc
bind *:443 ssl crt /etc/haproxy/cert/desktop.example.com.pem
mode http
...
default_backend be_rdp_tsc
backend be_rdp_tsc
...
mode http
...
#hozzunk létre egy táblázatot, sztring típusú, 1000 elemű, 15 másodperc múlva lejár, számoljuk az elmúlt 10 másodperc hibáit
stick-table type string len 128 size 1k expire 15s store http_err_rate(10s)
#jegyezzük meg az IP-t
http-request track-sc0 src
#tiltsuk le a 429-es HTTP hibával, ha az utolsó 10 másodpercben több mint 4 hiba történt
http-request deny deny_status 429 if { sc_http_err_rate(0) gt 4 }
...
server rdgw01 192.168.1.33:443 maxconn 1000 weight 10 ssl check cookie rdgw01
server rdgw02 192.168.2.33:443 maxconn 1000 weight 10 ssl check cookie rdgw02
Nem a legjobb megoldás, bonyolítsuk. Számítani fogunk a backend-en, és blokkolni a frontend-en.
A támadóval durván bánunk, TCP kapcsolatot fogunk megszakítani.
frontend fe_rdp_tsc
bind *:443 ssl crt /etc/haproxy/cert/ertelecom_ru_2020_06_11.pem
mode http
...
# IP címek táblázat létrehozása, 1000 elem, 15 másodperc után lejár, globális számlálóból megőrizni
stick-table type ip size 1k expire 15s store gpc0
# forrás lekérése
tcp-request connection track-sc0 src
# TCP kapcsolat elutasítása, ha a globális számláló >0
tcp-request connection reject if { sc0_get_gpc0 gt 0 }
...
default_backend be_rdp_tsc
backend be_rdp_tsc
...
mode http
...
# IP címek táblázat létrehozása, 1000 elem, 15 másodperc után lejár, hiba számának megőrzése 10 másodperc alatt
stick-table type ip size 1k expire 15s store http_err_rate(10s)
# sok hiba, ha a hibák száma 10 másodperc alatt meghaladja a 8-at
acl errors_too_fast sc1_http_err_rate gt 8
# támadás megjelölése a globális számlálóban (számláló növelése)
acl mark_as_abuser sc0_inc_gpc0(fe_rdp_tsc) gt 0
# globális számláló nullázása
acl clear_as_abuser sc0_clr_gpc0(fe_rdp_tsc) ge 0
# forrás lekérése
tcp-request content track-sc1 src
# elutasítás, támadás megjelölése
tcp-request content reject if errors_too_fast mark_as_abuser
# engedélyezni, támadás jelzésének törlése
tcp-request content accept if !errors_too_fast clear_as_abuser
...
server rdgw01 192.168.1.33:443 maxconn 1000 weight 10 ssl check cookie rdgw01
server rdgw02 192.168.2.33:443 maxconn 1000 weight 10 ssl check cookie rdgw02
ugyanaz, de udvariasan, HTTP 429 (Túl sok kérés) hibát fogunk visszaadni
frontend fe_rdp_tsc
...
stick-table type ip size 1k expire 15s store gpc0
http-request track-sc0 src
http-request deny deny_status 429 if { sc0_get_gpc0 gt 0 }
...
default_backend be_rdp_tsc
backend be_rdp_tsc
...
stick-table type ip size 1k expire 15s store http_err_rate(10s)
acl errors_too_fast sc1_http_err_rate gt 8
acl mark_as_abuser sc0_inc_gpc0(fe_rdp_tsc) gt 0
acl clear_as_abuser sc0_clr_gpc0(fe_rdp_tsc) ge 0
http-request track-sc1 src
http-request allow if !errors_too_fast clear_as_abuser
http-request deny deny_status 429 if errors_too_fast mark_as_abuser
...
Ellenőrzöm: elindítom az mstsc-t, és elkezdem véletlenszerűen beírni a jelszavakat. A harmadik kísérlet után 10 másodperc alatt kirúg, és az mstsc hibát jelez. Ezt a naplóban is látni lehet.
Magyarázatok. Messze nem vagyok a haproxy mestere. Nem értem, hogy például
http-request deny deny_status 429 if { sc_http_err_rate(0) gt 4 }
körülbelül 10 hibát engedélyez, mielőtt aktiválódik.
Zavarban vagyok a számlálókkal. A haproxy mestereit örömmel várom, ha kiegészítenek, javítanak, illetve jobban csinálják.
A megjegyzések között szívesen látnám a RD Gateway védelmének más módjait, érdekes lenne megismerni.
A Windows távoli asztali kliensek (mstsc) esetében meg kell jegyezni, hogy nem támogatják a TLS1.2-t (legalábbis Windows 7 alatt), így a TLS1-et kellett hagynom; nem támogatják a legfrissebb titkosítókat sem, így a régiakat kellett hagynom.
Azok számára, akik még semmit sem értettek meg, csak tanulnak, és már jót akarnak csinálni, minden konfigurációt bemutatok.
haproxy.conf
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
user haproxy
group haproxy
daemon
# Alapértelmezett SSL anyag helyek
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# Lásd: https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate
#ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
#ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
ssl-default-bind-options no-sslv3
ssl-server-verify none
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 15m
timeout server 15m
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
frontend fe_rdp_tsc
bind *:443 ssl crt /etc/haproxy/cert/dektop.example.com.pem
mode http
capture request header Host len 32
log global
option httplog
timeout client 300s
maxconn 1000
stick-table type ip size 1k expire 15s store gpc0
tcp-request connection track-sc0 src
tcp-request connection reject if { sc0_get_gpc0 gt 0 }
acl rdweb_domain hdr(host) -i beg dektop.example.com
http-request deny deny_status 400 if !rdweb_domain
default_backend be_rdp_tsc
backend be_rdp_tsc
balance source
mode http
log global
stick-table type ip size 1k expire 15s store http_err_rate(10s)
acl errors_too_fast sc1_http_err_rate gt 8
acl mark_as_abuser sc0_inc_gpc0(fe_rdp_tsc) gt 0
acl clear_as_abuser sc0_clr_gpc0(fe_rdp_tsc) ge 0
tcp-request content track-sc1 src
tcp-request content reject if errors_too_fast mark_as_abuser
tcp-request content accept if !errors_too_fast clear_as_abuser
option forwardfor
http-request add-header X-CLIENT-IP %[src]
option httpchk GET /
cookie RDPWEB insert nocache
default-server inter 3s rise 2 fall 3
server rdgw01 192.168.1.33:443 maxconn 1000 weight 10 ssl check cookie rdgw01
server rdgw02 192.168.2.33:443 maxconn 1000 weight 10 ssl check cookie rdgw02
frontend fe_stats
mode http
bind *:8080
acl ip_allow_admin src 192.168.66.66
stats enable
stats uri /stats
stats refresh 30s
#stats admin if LOCALHOST
stats admin if ip_allow_admin
Miért két szerver van a backend-en? Mert így lehet megszüntetni az egyetlen hibapontot. A HAProxy is létrehozhat két lebegő fehér IP-t.
Számítási erőforrások: lehet kezdeni a „két gigával, két maggal, játék PC-val”. E szerint ez bőven elegendő lesz.
Linkek:
Forrás: habr.com
