MS Remote Desktop Gateway, HAProxy ja parooli rĂŒnde kaitse

Tere, sÔbrad!

On mitmeid viise, kuidas kodust kontorisse ĂŒhendust luua. Üks neist on Microsoft Remote Desktop Gatewayi kasutamine. See on RDP ĂŒle HTTP. Ma ei soovi siin RDGW seadistamise teemasse minna, ega arutada, miks see on hea vĂ”i halb, kĂ€sitleme seda kui ĂŒhte kaugjuurdepÀÀsu tööriista. Soovin rÀÀkida RDGW serveri kaitsmisest kuri interneti eest. Kui seadistasin RDGW servereid, tegin kohe muretsemise prioriteediks, eriti parooli rĂŒnde kaitse. Mind ĂŒllatas, et ma ei leidnud internetist artikleid, kuidas seda saavutada. No mis teha, peab ise tegema.

RDGW-l endal ei ole mingit kaitset. Jah, seda saab seada paljaks liideseks avalikku vÔrku ja see töötab suurepÀraselt. Kuid korralik administraator vÔi IT-ettevÔtte spetsialist tunneb sellest Àrevust. Samuti aitab see vÀltida olukorda, kus arve blokeeritakse, kui hooletu töötaja on mingil pÔhjusel unustanud oma ettevÔtte konto parooli kodus olevasse arvutisse ja seejÀrel muutnud oma parooli.

Hea viis sisesisemete ressursside kaitsmiseks vĂ€lise keskkonna eest on erinevad proxid, avaldamissĂŒsteemid ja muud WAF-id. Peame meeles, et RDGW on siiski HTTP, seega kutsub see ĂŒles paigaldama spetsialiseeritud lahendust sisemiste serverite ja interneti vahele.

Ma tean, et on Ă€gedaid F5, A10, Netscaler(ADC). Ühe nende sĂŒsteemide administraatorina vĂ”in öelda, et nende sĂŒsteemide peal on ka vĂ”imalik parooli rĂŒnde kaitset seadistada. Ja jah, need sĂŒsteemid kaitsevad teid ka igasuguste syn rĂŒnnakute eest.

Kuid kaugelki mitte iga ettevÔte ei suuda sellist lahendust endale lubada (ja vajalikku administraatorit leida :), kuid julgeoleku peale saab siiski mÔelda!

On tĂ€iesti vĂ”imalik installida tasuta versioon HAProxy tasuta operatsioonisĂŒsteemile. Olen testinud Debian 10-l, stabiilses repositooriumis on versioon haproxy 1.8.19. Olen ka kontrollinud 2.0.xx versioone testimise repositooriumist.

Debiani seadistamine jÀÀb artikli piiridest vĂ€lja. LĂŒhidalt: avalikus liideses on sulgeda kĂ”ik, vĂ€lja arvatud 443 port, hallis liideses – vastavalt teie poliitikale, nĂ€iteks sulgeda kĂ”ik vĂ€lja arvatud 22 port. Avage ainult vajalik tööks (nt VRRP, nĂ€iteks ujuva ip jaoks).

Esiteks seadistasin haproxyle SSL sildamise reĆŸiimi (see on ka http reĆŸiim) ja lubasin logimise, et nĂ€ha, mis RDP kaudu juhtuma hakkab. Nii et, ĂŒtleme nii, et tungisin vahele. Olgu, kĂ”ikides RDGateway seadistamise artiklites viidatud rada /RDWeb puudub. Ainus, mis seal on, on /rpc/rpcproxy.dll ja /remoteDesktopGateway/. Samuti ei kasutata tavalisi GET/POST pĂ€ringuid, kasutatakse oma tĂŒĂŒpi pĂ€ringut RDG_IN_DATA, RDG_OUT_DATA.

Natuke, aga vÀhemalt midagi.

Alustame testimist.

KÀitan mstsc, suundun serverisse, logides nÀen nelja 401 (tohutu) viga, seejÀrel sisestan kasutajanime/parooli ja nÀen vastust 200.

Keelan, kÀitan uuesti, logis nÀen samu nelja 401 viga. Sisestan vale kasutajanime/parooli ja nÀen taas nelja 401 viga. See ongi vajalik. Seda hakkame jÀlgima.

Kuna login url'i mÀÀramine lĂ€ks pekki ja ma ei tea, kuidas haproxy's tĂ€pselt 401 vigu jĂ€lgida, siis jĂ€lgin (tegelikult loen) kĂ”iki 4xx vigu. See ka sobib ĂŒlesande lahendamiseks.

Kaitse idee seisneb selles, et loeme 4xx vigade arvu (backendis) ajaĂŒhiku jooksul ja kui see ĂŒletab mÀÀratud piiri, siis keelame (frontendis) kĂ”ik edasised ĂŒhendused sellest ip-st mÀÀratud ajaks.

Tehniliselt ei ole see kaitse paroolide bruteforce'i vastu, vaid kaitse 4xx vigade eest. NĂ€iteks kui pidevalt kĂŒsida mitteeksisteerivat url'i (404), siis kaitse aktiveerub.

Lihtsaim ja toimiv viis — see on backendis lugemine ja ĂŒleliigsete korral tagastamine:

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
    ...

    #luua tabel, stringitĂŒĂŒp, 1000 elementi, aegub 15 sekundi pĂ€rast, salvestada vigade arv viimase 10 sekundi jooksul
    stick-table type string len 128 size 1k expire 15s store http_err_rate(10s)
    #salvestada ip
    http-request track-sc0 src
    #keelata 429 http veaga, kui viimase 10 sekundi jooksul on rohkem kui 4 viga
    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

See pole kÔige parem lahendus, muudame keerulisemaks. Loeme backendis, blokeerime frontendis.

KĂ€itleme rĂŒndajaga karmilt, blokeerime TCP-ĂŒhenduse.

frontend fe_rdp_tsc
    bind *:443 ssl crt /etc/haproxy/cert/ertelecom_ru_2020_06_11.pem
    mode http
    ...
    # looja IP-aadresside tabel, 1000 elementi, aegub 15 sekundi pÀrast, salvestab globaalsest loendurist
tick-table type ip size 1k expire 15s store gpc0
    # vÔta allikas
    tcp-request connection track-sc0 src
    # tagasi lĂŒkata tcp ĂŒhendus, kui globaalne loendur >0
    tcp-request connection reject if { sc0_get_gpc0 gt 0 }
	
    ...
    default_backend be_rdp_tsc


backend be_rdp_tsc
    ...
    mode http
    ...
	
    # loo IP-aadresside tabel, 1000 elementi, aegub 15 sekundi pÀrast, salvestab vigade arvu 10 sekundi jooksul
tick-table type ip size 1k expire 15s store http_err_rate(10s)
    # liiga palju vigu, kui vigade arv 10 sekundi jooksul ĂŒletab 8
    acl errors_too_fast sc1_http_err_rate gt 8
    # mĂ€rgi rĂŒnnak globaalses loenders (suurema loenduri)
    acl mark_as_abuser sc0_inc_gpc0(fe_rdp_tsc) gt 0
    # nulli globaalne loendur
    acl clear_as_abuser sc0_clr_gpc0(fe_rdp_tsc) ge 0
    # vÔta allikas
    tcp-request content track-sc1 src
    # tagasi lĂŒkata, mĂ€rgi, et on rĂŒnnak
    tcp-request content reject if errors_too_fast mark_as_abuser
    # luba, tĂŒhista rĂŒnnakulipp
    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

tÀpselt sama, aga viisakam, tagastame HTTP 429 ( liiga palju pÀringuid) veateate

frontend fe_rdp_tsc
    ...
    tick-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
    ...
    tick-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
    ...

Kontrollin: kÀivitan mstsc ja hakkan suvaliselt paroole sisestama. PÀrast kolmandat katset 10 sekundi jooksul visatakse mind vÀlja ning mstsc annab vea. Seda on nÀha logides.

Selgitused. Ma ei ole haproxy meister. Ma ei mÔista, miks nÀiteks
http-request deny deny_status 429 if { sc_http_err_rate(0) gt 4 }
lubab teha umbes 10 viga, enne kui see aktiveerub.

Ma segadusse oma loenduri numbritega. Haproxy meistrid, oleksin tÀnulik, kui saaksite mind tÀiendada, parandada, teha paremini.

Kommentaarides vÔite visata vÀlja teisi RD Gateway kaitse meetodeid, oleks huvitav uurida.

Mis puudutab Windowsi kaugjÀrgijate klienti (mstsc), siis tasub mÀrkida, et see ei toeta TLS1.2 (vÀhemalt Windows 7-s), seetÔttu tuli jÀtta TLS1; ei toeta kaasaegseid cipher'e, seega tuli samuti jÀtta vanad.

Neile, kes ei saanud aru ja alles Ôpivad, aga juba tahavad hÀsti teha, toome vÀlja kogu konfiguratsiooni.

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

        # Vaata: 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

Miks on backend'is kaks serverit? Sest nii saab tagada sĂŒsteemi talitlushĂ€irete korral töökindluse. Haproxy'ga saab samuti luua kaks ujuvat avalikku IP-d.

Arvutusressursid: vĂ”id alustada "kaks gigabaiti, kaks tuuma, mĂ€ngur ПК". Vastavalt vikipeediale selleks on piisavalt varu.

Lingid:

RDP-gateway seadistamine HAProxy katalooge.
Ainuke artikkel, mille leidsin, kus tegeletakse paroolide proovimisega

Allikas: habr.com

Osta usaldusvÀÀrne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid | ProHoster