Barátaim, sziasztok!
Számos módja van annak, hogy otthonról kapcsolódjon az irodai munkaterülethez. Az egyik a Microsoft Remote Desktop Gateway használata. Ez az RDP HTTP-n keresztül. Magát az RDGW beállítását itt nem akarom érinteni, nem akarom taglalni, hogy miért jó vagy rossz, tekintsük a távoli elérési eszközök egyikeként. Arról szeretnék beszélni, hogy megvédje RDGW-kiszolgálóját a gonosz internettől. Amikor beállítottam az RDGW szervert, azonnal aggódni kezdtem a biztonság miatt, különösen a jelszóval való nyers erőszak elleni védelem miatt. Meglepődtem, hogy az interneten egyetlen cikket sem találtam ennek módjáról. Nos, magának kell megtennie.
Az RDGW önmagában nem rendelkezik védelemmel. Igen, csupasz interfésszel ki lehet tenni fehér hálózatra, és remekül fog működni. Ez azonban nyugtalanítja a megfelelő rendszergazdát vagy információbiztonsági szakembert. Ezenkívül lehetővé teszi a fiók blokkolásának elkerülését, amikor egy gondatlan alkalmazott megjegyezte a vállalati fiók jelszavát az otthoni számítógépén, majd megváltoztatta a jelszavát.
A belső erőforrások külső környezettől való védelmének jó módja a különféle proxy-k, közzétételi rendszerek és egyéb WAF-ok. Emlékezzünk arra, hogy az RDGW továbbra is http, akkor már csak egy speciális megoldást kell csatlakoztatni a belső szerverek és az internet közé.
Tudom, hogy vannak menő F5, A10, Netscaler(ADC). Az egyik ilyen rendszer adminisztrátoraként elmondom, hogy ezeken a rendszereken is be lehet állítani védelmet a nyers erő ellen. És igen, ezek a rendszerek megvédenek minden szin áradattól.
De nem minden cég engedheti meg magának, hogy ilyen megoldást vásároljon (és keressen rendszergazdát egy ilyen rendszerhez :), de ugyanakkor a biztonságról is gondoskodhat!
Teljesen lehetséges a HAProxy ingyenes verziójának telepítése ingyenes operációs rendszerre. A Debian 10, haproxy 1.8.19-es verzióját teszteltem a stabil tárolóban. A tesztelési tárhely 2.0.xx verzióján is teszteltem.
Magát a debian beállítását a cikk keretein kívül hagyjuk. Röviden: a fehér felületen zárjon be mindent, kivéve a 443-as portot, a szürke felületen - például a házirendje szerint zárjon be mindent, kivéve a 22-es portot. Csak azt nyissa meg, ami a munkához szükséges (VRRP például lebegő ip-hez).
Először is beállítottam a haproxyt SSL áthidaló módban (más néven http módban), és bekapcsoltam a naplózást, hogy megnézzem, mi történik az RDP-n belül. Úgymond középre kerültem. Tehát az RDGateway beállításáról szóló „minden” cikkben megadott /RDWeb elérési út hiányzik. Csak az /rpc/rpcproxy.dll és a /remoteDesktopGateway/ található. Ebben az esetben a szabványos GET/POST kérések nem használatosak, hanem a saját kéréstípusuk (RDG_IN_DATA, RDG_OUT_DATA) használatos.
Nem sok, de legalább valami.
Teszteljük.
Elindítom az mstsc-t, felmegyek a szerverre, négy 401-es (illetéktelen) hibát látok a naplókban, majd beírom a felhasználónevemet/jelszavamat és látom a 200-as választ.
Kikapcsolom, újraindítom, és a naplókban ugyanazt a négy 401-es hibát látom. Rossz bejelentkezési/jelszót írok be, és újra négy 401-es hibát látok. Erre van szükségem. Ezt fogjuk kifogni.
Mivel nem lehetett meghatározni a bejelentkezési url-t, és emellett nem tudom, hogyan lehet elkapni a 401-es hibát a haproxyban, ezért fogom (valójában nem fogom, hanem számolom) az összes 4xx hibát. A probléma megoldására is alkalmas.
A védelem lényege az lesz, hogy időegységenként megszámoljuk a 4xx hibák számát (a háttérben) és ha ez meghaladja a megadott határt, akkor elutasítunk (a frontenden) minden további kapcsolatot erről az IP-ről a megadott ideig. .
Technikailag ez nem a jelszó brute force elleni védelem lesz, hanem a 4xx hibák ellen. Például, ha gyakran kér egy nem létező url-t (404), akkor a védelem is működni fog.
A legegyszerűbb és leghatékonyabb módja, ha számítunk a háttérre, és jelentünk, ha bármi extra 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
...
#создать таблицу, строковую, 1000 элементов, протухает через 15 сек, записать кол-во ошибок за последние 10 сек
stick-table type string len 128 size 1k expire 15s store http_err_rate(10s)
#запомнить ip
http-request track-sc0 src
#запретить с http ошибкой 429, если за последние 10 сек больше 4 ошибок
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 le. A háttérben számolunk, a frontenden pedig a blokkolással.
Durván bánunk a támadóval, és megszakítjuk a TCP-kapcsolatát.
frontend fe_rdp_tsc
bind *:443 ssl crt /etc/haproxy/cert/ertelecom_ru_2020_06_11.pem
mode http
...
#создать таблицу ip адресов, 1000 элементов, протухнет через 15 сек, сохрянять из глобального счётчика
stick-table type ip size 1k expire 15s store gpc0
#взять источник
tcp-request connection track-sc0 src
#отклонить tcp соединение, если глобальный счётчик >0
tcp-request connection reject if { sc0_get_gpc0 gt 0 }
...
default_backend be_rdp_tsc
backend be_rdp_tsc
...
mode http
...
#создать таблицу ip адресов, 1000 элементов, протухнет через 15 сек, сохранять кол-во ошибок за 10 сек
stick-table type ip size 1k expire 15s store http_err_rate(10s)
#много ошибок, если кол-во ошибок за 10 сек превысило 8
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
...
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 visszaadjuk a http 429-es hibát (Túl sok kérés)
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 próbálkozás után 10 másodpercen belül visszarúg, és az mstsc hibát ad. Ahogy a naplókban is látszik.
Magyarázatok. Messze vagyok a haproxy mestertől. Nem értem miért pl
http-request deny deny_status 429 if { sc_http_err_rate(0) gt 4 }
lehetővé teszi, hogy körülbelül 10 hibát kövessen el, mielőtt működne.
Zavarban vagyok a számlálók számozásával kapcsolatban. Haproxy mesterei, örülök, ha kiegészítenek, javítanak, jobbá tesznek.
A megjegyzésekben javasolhat más módszereket az RD Gateway védelmére, érdekes lesz tanulmányozni.
A Windows Remote Desktop Client (mstsc) kapcsán érdemes megjegyezni, hogy az nem támogatja a TLS1.2-t (legalábbis Windows 7-ben), így el kellett hagynom a TLS1-et; nem támogatja a jelenlegi titkosítást, ezért a régieket is elhagynom kellett.
Azok számára, akik nem értenek semmit, csak tanulnak, és már jól akarnak járni, azoknak megadom a teljes konfigurációt.
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
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# See: 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 van két szerver a háttérben? Mert így lehet hibatűrést kialakítani. A Haproxy lebegő fehér ip-vel is tud kettőt csinálni.
Számítástechnikai erőforrások: kezdheti a „két koncert, két mag, játék PC”-vel. Alapján
referenciák:
Forrás: will.com