SÀkerhet och DBMS: vad man bör tÀnka pÄ vid val av skyddsmekanismer

SÀkerhet och DBMS: vad man bör tÀnka pÄ vid val av skyddsmekanismer

Jag heter Denis Rozhkov, jag Àr ansvarig för mjukvaruutveckling pÄ företaget "Gazinformservice", i produktteamet. Jatoba. Lagstiftning och företagsnormer stÀller vissa krav pÄ sÀkerheten vid datalagring. Ingen vill att tredje part ska fÄ tillgÄng till kÀnslig information, dÀrför Àr följande frÄgor viktiga för varje projekt: identifiering och autentisering, hantering av Ätkomst till data, sÀkerstÀllande av informationens integritet i systemet, registrering av sÀkerhetshÀndelser. DÀrför vill jag berÀtta om nÄgra intressanta aspekter av databasens sÀkerhet.

Artikeln Àr baserad pÄ ett föredrag vid @Databases Meetup, organiserat Mail.ru Cloud Solutions. Om du inte vill lÀsa kan du titta:

Spela video

Artikeln kommer att bestÄ av tre delar:
  • Hur man skyddar anslutningar.
  • Vad Ă€r aktivitetsgranskning och hur registrerar man vad som hĂ€nder med databasen och anslutningen till den.
  • Hur man skyddar data i sjĂ€lva databasen och vilka teknologier som finns för detta.

SÀkerhet och DBMS: vad man bör tÀnka pÄ vid val av skyddsmekanismer
Tre aspekter av databasens sÀkerhet: skydd av anslutningar, aktivitetsgranskning och dataskydd.

Skydd av anslutningar

Man kan ansluta till databasen antingen direkt eller indirekt via webbapplikationer. Vanligtvis interagerar en affÀrsanvÀndare, det vill sÀga en person som arbetar med databas, inte direkt med den.

Innan vi pratar om hur man skyddar anslutningar, mÄste vi svara pÄ viktiga frÄgor som avgör hur sÀkerhetsÄtgÀrderna kommer att utformas:

  • Ă€r en affĂ€rsanvĂ€ndare motsvarande en anvĂ€ndare i databasen;
  • ges Ă„tkomst till databasen endast genom ett API som du kontrollerar, eller finns det direkt Ă„tkomst till tabeller;
  • Ă€r databasen avgrĂ€nsad till ett separat skyddat segment, vem och hur interagerar med den;
  • anvĂ€nds det poolning/proxy och mellanliggande lager som kan Ă€ndra information om hur anslutningen Ă€r uppbyggd och vem som anvĂ€nder databasen.

LÄt oss nu titta pÄ vilka verktyg som kan anvÀndas för att skydda anslutningarna:

  1. AnvÀnd lösningar av typen databasbrandvÀgg. Ett extra skyddslag kan Ätminstone öka transparensen för vad som hÀnder i databasen, och som högst kan du sÀkerstÀlla ett extra skydd för data.
  2. AnvÀnd lösenordspolicyer. Deras tillÀmpning beror pÄ hur din arkitektur Àr uppbyggd. I vilket fall som helst, enbart ett lösenord i konfigurationsfilen för webbtjÀnsten som ansluter till databas hanteringssystemet (DBMS) Àr otillrÀckligt för skydd. Det finns flera verktyg för DBMS som gör det möjligt att kontrollera vilka anvÀndare och lösenord som behöver uppdateras.

    LÀs mer om funktionerna för utvÀrdering av anvÀndare. hÀr, Àven hur man fÄr information om MS SQL Vulnerability Assessment. ). Ett typiskt exempel pÄ anvÀndning:. 

  3. Berika sessionens kontext med nödvÀndig information. Om sessionen Àr ogenomskinlig, kan du inte förstÄ vem som arbetar inom dess ram i DBMS. Du kan komplettera informationen om vem som gör vad och varför inom ramen för den genomförda operationen. Denna information kan ses i revisionen.
  4. Konfigurera SSL om du inte har nÀtverksavgrÀnsning mellan DBMS och slutanvÀndarna; den Àr inte i ett separat VLAN. I sÄdana fall Àr det avgörande att skydda kanalen mellan konsumenten och sjÀlva DBMS. Skyddsverktyg finns Àven bland open source-lösningar.

Hur pÄverkar detta DBMS-prestandan?

LÄt oss titta pÄ hur SSL pÄverkar CPU-belastningen, ökar latensen och minskar TPS i PostgreSQL. Kommer det att gÄ för mycket resurser om det aktiveras?

Vi belastar PostgreSQL med pgbench — ett enkelt program för att köra prestandatest. Det kör en sekvens av kommandon upprepade gĂ„nger, eventuellt i parallella databas-sessioner, och berĂ€knar det genomsnittliga transaktionshastigheten.

Test 1 utan SSL och med anvĂ€ndning av SSL. — anslutningen upprĂ€ttas vid varje transaktion:

pgbench.exe --connect -c 10 -t 5000 "host=192.168.220.129 dbname=taskdb user=postgres sslmode=require
sslrootcert=rootCA.crt sslcert=client.crt sslkey=client.key"

vs

pgbench.exe --connect -c 10 -t 5000 "host=192.168.220.129 dbname=taskdb user=postgres"

Test 2 utan SSL och med anvĂ€ndning av SSL. — alla transaktioner utförs i en anslutning:

pgbench.exe -c 10 -t 5000 "host=192.168.220.129 dbname=taskdb user=postgres sslmode=require
sslrootcert=rootCA.crt sslcert=client.crt sslkey=client.key"

vs

pgbench.exe -c 10 -t 5000 "host=192.168.220.129 dbname=taskdb user=postgres"

Övriga instĂ€llningar:

skaleringsfaktor: 1
frÄgemode: enkel
antal kunder: 10
antal trÄdar: 1
antal transaktioner per kund: 5000
antal transaktioner som faktiskt behandlades: 50000/50000

Testresultat:

 
INGA SSL
SSL

En anslutning upprÀttas vid varje transaktion.

latens genomsnitt
171.915 ms
187.695 ms

tps inklusive anslutningar som etableras
58.168112
53.278062

tps utan att inkludera anslutningar som etableras
64.084546
58.725846

CPU
24%
28%

Alla transaktioner utförs i en anslutning.

latens genomsnitt
6.722 ms
6.342 ms

tps inklusive anslutningar som etableras
1587.657278
1576.792883

tps utan att inkludera anslutningar som etableras
1588.380574
1577.694766

CPU
17%
21%

Vid smÄ belastningar Àr pÄverkan av SSL jÀmförbar med mÀtfel. Om mÀngden överförda data Àr mycket stor kan situationen vara annorlunda. Om vi etablerar en anslutning för varje transaktion (vilket sÀllan sker, vanligtvis delas anslutningen mellan anvÀndare), fÄr du ett stort antal anslutningar/diskonnekter, och pÄverkan kan vara nÄgot större. Det vill sÀga att det finns risker för prestandaförlust, men skillnaden Àr inte sÄ stor att skyddet bör avstÄs frÄn.

Observera att det finns en stor skillnad nÀr man jÀmför driftslÀgen: inom en session arbetar du eller olika. Det Àr förstÄeligt: resurser anvÀnds för att skapa varje anslutning.

Vi hade ett fall dÀr vi kopplade samman Zabbix i trust-lÀge, vilket innebÀr att md5 inte kontrollerades, det fanns ingen anledning till autentisering. DÀrefter bad kunden att aktivera md5-autentisering. Detta gav en stor belastning pÄ CPU:n, prestandan sjönk. Vi började leta efter sÀtt att optimera. En av de möjliga lösningarna pÄ problemet Àr att implementera nÀtverksbegrÀnsningar, skapa separata VLAN för DBMS, lÀgga till instÀllningar för att förstÄ vem som ansluter och varifrÄn och ta bort autentiseringen. Man kan ocksÄ optimera autentiseringsinstÀllningar för att minska kostnaderna vid aktivering av autentisering, men generellt pÄverkar anvÀndningen av olika autentiseringsmetoder prestandan och dessa faktorer mÄste beaktas vid designen av serverkapacitet (hÄrdvara) för DBMS.

Slutsats: i en rad lösningar kan Àven smÄ detaljer kring autentisering fÄ stor inverkan pÄ projektet, och det Àr olyckligt nÀr detta först blir tydligt vid implementering i produktion.

Aktivitetens granskning

Granskning behöver inte vara begrÀnsad till DBMS. Granskning Àr att erhÄlla information om vad som hÀnder pÄ olika segment. Detta kan inkluderar bÄde en databasbrandvÀgg och operativsystemet som DBMS byggs pÄ.

I kommersiella DBMS av Enterprise-nivÄ fungerar granskning bra, men i öppen kÀllkod Àr det inte alltid sÄ. HÀr Àr vad som finns i PostgreSQL:

  • default log — inbyggd loggning;
  • extensions: pgaudit — om du behöver mer Ă€n standardloggningen kan du anvĂ€nda separata instĂ€llningar som löser en del uppgifter.

TillÀgg till rapporten i videon:

Den grundlÀggande registreringen av operatörer kan sÀkerstÀllas med hjÀlp av ett standardloggningsverktyg med log_statement = all.

Detta Àr acceptabelt för övervakning och andra anvÀndningsomrÄden, men ger inte den detaljnivÄ som vanligtvis krÀvs för revision.

Det rÀcker inte med att ha en lista över alla operationer som utförs med databasen.

Det mÄste ocksÄ finnas möjlighet att hitta specifika pÄstÄenden som Àr av intresse för revisorn.

Standardloggningsverktyget visar vad anvÀndaren har begÀrt, medan pgAudit fokuserar pÄ detaljerna kring vad som hÀnde nÀr databasen utförde begÀran.

Till exempel kan revisorn vilja försÀkra sig om att en specifik tabell skapades under det dokumenterade underhÄllsfönstret.

Det kan verka vara en enkel uppgift för grundlÀggande revision och grep, men vad hÀnder om du pÄtrÀffar nÄgot som detta (medvetet otydliga) exempel:

DO $$
BEGIN
EXECUTE ‘CREATE TABLE import’ || ‘ant_table (id INT)’;
END $$;

Standardloggningen ger dig detta:

LOG: statement: DO $$
BEGIN
EXECUTE ‘CREATE TABLE import’ || ‘ant_table (id INT)’;
END $$;

Det verkar som om viss kodkunskap kan behövas för att hitta den tabell som Àr av intresse, nÀr tabeller skapas dynamiskt.

Detta Àr inte perfekt, eftersom det skulle vara att föredra att bara söka pÄ tabellnamn.

HÀr kommer pgAudit att vara anvÀndbart.

För samma inmatning kommer det att ge denna loggutgÄng:

AUDIT: SESSION,33,1,FUNCTION,DO,,,«DO $$
BEGIN
EXECUTE ‘CREATE TABLE import’ || ‘ant_table (id INT)’;
END $$;"
AUDIT: SESSION,33,2,DDL,CREATE TABLE,TABLE,public.important_table,CREATE TABLE important_table (id INT)

Inte bara blocket DO registreras, utan ocksÄ den fullstÀndiga texten för CREATE TABLE med typ av operation, objekttyp och fullstÀndigt namn, vilket gör det lÀttare att söka.

Vid registrering av SELECT- och DML-operationer kan pgAudit konfigureras för att registrera en separat post för varje relation som refereras i operationen.

Ingen syntaktisk analys krÀvs för att hitta alla operationer som rör en specifik tabell (*)».

Hur pÄverkar detta DBMS-prestandan?

LÄt oss göra tester med fullstÀndig revision aktiverad och se hur det pÄverkar prestandan i PostgreSQL. Vi aktiverar maximal databasloggning för alla parametrar.

Vi Àndrar nÀstan ingenting i konfigurationsfilen, det viktiga Àr att vi aktiverar debug5-lÀget för att fÄ maximal information.

postgresql.conf

log_destination = ‘stderr’
logging_collector = on
log_truncate_on_rotation = on
log_rotation_age = 1d
log_rotation_size = 10MB
log_min_messages = debug5
log_min_error_statement = debug5
log_min_duration_statement = 0
debug_print_parse = on
debug_print_rewritten = on
debug_print_plan = on
debug_pretty_print = on
log_checkpoints = on
log_connections = on
log_disconnections = on
log_duration = on
log_hostname = on
log_lock_waits = on
log_replication_commands = on
log_temp_files = 0
log_timezone = 'Europe/Moscow'

PÄ PostgreSQL DB med parametrarna 1 CPU, 2,8 GHz, 2 GB RAM, 40 GB HDD genomför vi tre belastningstester med kommandon:

$ pgbench -p 3389 -U postgres -i -s 150 benchmark
$ pgbench -p 3389 -U postgres -c 50 -j 2 -P 60 -T 600 benchmark
$ pgbench -p 3389 -U postgres -c 150 -j 2 -P 60 -T 600 benchmark

Testresultat:

Utan loggning
Med loggning

Total tiden för att fylla databasen
43,74 sek
53,23 sek

RAM
24%
40%

CPU
72%
91%

Test 1 (50 anslutningar)

Antal transaktioner pÄ 10 minuter
74169
32445

Transaktioner/sek
123
54

Genomsnittlig fördröjning
405 ms
925 ms

Test 2 (150 anslutningar av 100 möjliga)

Antal transaktioner pÄ 10 minuter
81727
31429

Transaktioner/sek
136
52

Genomsnittlig fördröjning
550 ms
1432 ms

Om storlekar

Databasens storlek
2251 MB
2262 MB

Loggarnas storlek
0 MB
4587 MB

I slutÀndan: en fullstÀndig revision Àr inte sÄ bra. MÀngden data som genereras frÄn revisionen blir ungefÀr lika stor som datan i sjÀlva databasen, om inte mer. Den mÀngd loggning som genereras vid arbete med DBMS Àr ett vanligt problem i produktion.

LÄt oss titta pÄ andra parametrar:

  • Hastigheten förĂ€ndras inte mycket: utan loggning — 43,74 sek, med loggning — 53,23 sek.
  • Prestandan för RAM och CPU kommer att sjunka, eftersom en fil med revision mĂ„ste skapas. Detta Ă€r ocksĂ„ tydligt i produktionen.

Vid en ökning av antalet anslutningar kommer givetvis vÀrdena att försÀmras nÄgot.

I företag med revision Àr det Ànnu mer komplicerat:

  • det finns mycket data;
  • revision behövs inte bara via syslog i SIEM, utan ocksĂ„ i filer: om nĂ„got skulle hĂ€nda med syslog, mĂ„ste det finnas en fil nĂ€ra databasen dĂ€r uppgifterna sparas;
  • för revision behövs en separat hylla för att inte överbelasta I/O pĂ„ diskarna, eftersom den tar mycket plats;
  • det kan hĂ€nda att anstĂ€llda inom IT-sĂ€kerhet krĂ€ver standarder, de krĂ€ver giltig identifikation.

BegrÀnsning av tillgÄngen till data

LÄt oss se pÄ teknologierna som anvÀnds för att skydda data och begrÀnsa Ätkomst till dem i kommersiella DBMS och open source.

Vad som generellt kan anvÀndas:

  1. Kryptering och obfuskering av procedurer och funktioner (Wrapping) — det vill sĂ€ga specifika verktyg och hjĂ€lpmedel som gör lĂ€sbar kod olĂ€slig. TyvĂ€rr kan den inte Ă€ndras eller refaktoreras tillbaka. Denna metod behövs ibland Ă„tminstone pĂ„ DBMS-sidan — logiken för licensbegrĂ€nsningar eller autentisering krypteras just pĂ„ nivĂ„erna för procedurer och funktioner.
  2. BegrÀnsning av datavisibilitet per rad (RLS) innebÀr att olika anvÀndare ser en tabell, men med olika innehÄll per rad, vilket betyder att vissa anvÀndare inte kan se viss information pÄ radsnivÄ.
  3. Redigering av visade data (Masking) innebÀr att anvÀndare i en kolumn i tabellen antingen ser data eller bara stjÀrnor, vilket innebÀr att viss information Àr stÀngd för vissa anvÀndare. Tekniken avgör vilken information som visas för vilken anvÀndare baserat pÄ ÄtkomstnivÄ.
  4. Åtkomstkontroll Security DBA/Application DBA/DBA handlar snarare om att begrĂ€nsa Ă„tkomst till sjĂ€lva databashanteringssystemet, vilket betyder att sĂ€kerhetspersonal kan Ă„tskiljas frĂ„n databasadministratörer och applikationsadministratörer. Det finns fĂ„ sĂ„dana teknologier i open source, men det finns gott om dem i kommersiella databashanteringssystem. De Ă€r nödvĂ€ndiga nĂ€r mĂ„nga anvĂ€ndare har Ă„tkomst till servrarna sjĂ€lva.
  5. ÅtkomstbegrĂ€nsning pĂ„ filsystemsnivĂ„. RĂ€ttigheter och Ă„tkomstrĂ€ttigheter kan ges till kataloger sĂ„ att varje administratör endast fĂ„r Ă„tkomst till nödvĂ€ndig data.
  6. MandatÄtkomst och minnesrensning Àr teknologier som sÀllan tillÀmpas.
  7. End-to-end-kryptering direkt i databashanteringssystemet innebÀr klientbaserad kryptering med nyckelhantering pÄ serversidan.
  8. Kryptering av data. Till exempel kolumnkryptering – nĂ€r du anvĂ€nder en mekanism som krypterar enskilda kolumner i databasen.

Hur pÄverkar detta prestandan hos databashanteringssystemet?

LÄt oss titta pÄ kolumnkryptering i PostgreSQL som exempel. Den har modulen pgcrypto, som gör det möjligt att lagra utvalda fÀlt i krypterad form. Detta Àr anvÀndbart nÀr endast vissa data Àr vÀrdefulla. För att lÀsa krypterade fÀlt skickar klienten den avkrypterande nyckeln, servern avkrypterar data och skickar dem till klienten. Utan nyckeln kan ingen göra nÄgot med dina data.

Vi genomför ett test med pgcrypto.. Vi skapar en tabell med krypterade data och en med vanliga data. Nedan Àr kommandon för att skapa tabeller, i den första raden finns ett anvÀndbart kommando - skapande av den aktuella extensionen med registrering av databashanteringssystemet:

CREATE EXTENSION pgcrypto;
CREATE TABLE t1 (id integer, text1 text, text2 text);
CREATE TABLE t2 (id integer, text1 bytea, text2 bytea);
INSERT INTO t1 (id, text1, text2)
VALUES (generate_series(1,10000000), generate_series(1,10000000)::text, generate_series(1,10000000)::text);
INSERT INTO t2 (id, text1, text2) VALUES (
generate_series(1,10000000),
encrypt(cast(generate_series(1,10000000) AS text)::bytea, 'key'::bytea, 'bf'),
encrypt(cast(generate_series(1,10000000) AS text)::bytea, 'key'::bytea, 'bf'));

LÄt oss nu försöka göra dataval för varje tabell och titta pÄ exekveringstiderna.

Dataval frÄn tabellen utan krypteringsfunktion:

psql -c "timing" -c "select * from t1 limit 1000;" "host=192.168.220.129 dbname=taskdb
user=postgres sslmode=disable" > 1.txt

Tidtagarur aktiverat.

  id | text1 | text2
——+——-+——-
1 | 1     | 1
2 | 2     | 2
3 | 3     | 3


997 | 997   | 997
998 | 998   | 998
999 | 999   | 999
1000 | 1000  | 1000
(1000 rader)

Tid: 1,386 ms

Dataval frÄn tabellen med krypteringsfunktion:

psql -c "timing" -c "select id, decrypt(text1, 'key'::bytea, 'bf'),
decrypt(text2, 'key'::bytea, 'bf') from t2 limit 1000;"
"host=192.168.220.129 dbname=taskdb user=postgres sslmode=disable" > 2.txt

Tidtagarur aktiverat.

  id | decrypt | decrypt
——+—————+————
1 | x31 | x31
2 | x32 | x32
3 | x33 | x33


999 | x393939 | x393939
1000 | x31303030 | x31303030
(1000 rader)

Tid: 50,203 ms

Testresultat:

 
Utan kryptering
Pgcrypto (decrypt)

Dataval 1000 rader
1,386 ms
50,203 ms

CPU
15%
35%

RAM
 
+5%

Kryptering pÄverkar prestandan avsevÀrt. Det Àr tydligt att tiden ökade eftersom avkrypteringsoperationer för krypterade data (och avkryptering Àr vanligtvis ocksÄ inbÀddad i din logik) krÀver betydande resurser. Det vill sÀga, idén att kryptera alla kolumner som innehÄller data kan leda till prestandanedsÀttning.

Samtidigt Àr kryptering inte en silverkula som löser alla problem. De avkrypterade data och avkrypteringsnyckeln finns pÄ servern under processen av avkryptering och dataöverföring. DÀrför kan nycklar bli avlyssnade av dem som har fullstÀndig Ätkomst till databasservern, till exempel systemadministratörer.

NĂ€r en nyckel anvĂ€nds för hela kolumnen för alla anvĂ€ndare (Ă€ven om det bara Ă€r för en begrĂ€nsad uppsĂ€ttning kunder), Ă€r det inte alltid bra och korrekt. Det Ă€r dĂ€rför end-to-end-kryptering började implementeras, och alternativ för kryptering av data frĂ„n klientsidan och servern diskuterades inom databashanteringssystem, vilket ledde till framvĂ€xten av key-vault-lösningar — sĂ€rskilda produkter som tillhandahĂ„ller nyckelhantering pĂ„ databashanteringssystemets sida.

SÀkerhet och DBMS: vad man bör tÀnka pÄ vid val av skyddsmekanismer
Exempel pÄ sÄdan kryptering i MongoDB

SĂ€kerhetsverktyg i kommersiella och open source databashanteringssystem

Funktioner
Typ
Lösenordspolicy
Revision
Skydd av kÀllkoden för procedurer och funktioner
RLS
Kryptering

Oracle
Kommersiell
+
+
+
+
+

MsSql
Kommersiell
+
+
+
+
+

Jatoba
Kommersiell
+
+
+
+
tillÀgg

PostgreSQL
Gratis
tillÀgg
tillÀgg
—
+
tillÀgg

MongoDb
Gratis
—
+
—
—
Endast tillgÀnglig i MongoDB Enterprise

Tabellen Ă€r lĂ„ngt ifrĂ„n komplett, men situationen Ă€r följande: i kommersiella produkter har sĂ€kerhetsuppgifter lĂ€nge lösts, i open source-produkter anvĂ€nds vanligtvis överliggande lösningar för sĂ€kerhet, mĂ„nga funktioner saknas, ibland mĂ„ste nĂ„got skrivas till. Till exempel, lösenordspolicys — det finns mĂ„nga olika tillĂ€gg i PostgreSQL.1, 2, 3, 4, 5), som implementerar lösenordspolicys, men alla behov inom den inhemska företagssektorn, enligt min mening, tĂ€cker ingen av dem.

Vad ska man göra om det man behöver inte finns nĂ„gonstans?? ĐĐ°ĐżŃ€ĐžĐŒĐ”Ń€, Ń…ĐŸŃ‡Đ”Ń‚ŃŃ ĐžŃĐżĐŸĐ»ŃŒĐ·ĐŸĐČать ĐŸĐżŃ€Đ”ĐŽĐ”Đ»Đ”ĐœĐœŃƒŃŽ СУБД, ĐČ ĐșĐŸŃ‚ĐŸŃ€ĐŸĐč ĐœĐ”Ń‚ Ń„ŃƒĐœĐșцоĐč, ĐșĐŸŃ‚ĐŸŃ€Ń‹Đ” Ń‚Ń€Đ”Đ±ŃƒĐ”Ń‚ заĐșазчОĐș.

DÄ kan man anvÀnda externa lösningar som fungerar med olika databashanteringssystem, till exempel «Krypto DB» eller «Garda DB». Om det handlar om lösningar frÄn den inhemska sektorn, sÄ kÀnner de till GOST bÀttre Àn i open source.

Det andra alternativet Àr att sjÀlv skriva vad som behövs, implementera Ätkomst till data och kryptering pÄ applikationsnivÄ. Visserligen kan det bli mer komplicerat med GOST. Men allt som allt - du kan dölja data som behövs, lagra den i databashanteringssystemet, och sedan hÀmta och dekryptera den som behövs, direkt pÄ applikationsnivÄ. TÀnk ocksÄ pÄ hur du kommer att skydda dessa algoritmer pÄ applikationen. Enligt vÄr Äsikt bör detta göras pÄ databashanteringssystemets nivÄ, eftersom det kommer att fungera snabbare.

Denna presentation hördes först pÄ @Databases Meetup av Mail.ru Cloud Solutions. Se video andra förelÀsningar och följ anmÀlningarna till evenemang pÄ Telegram Runt Kubernetes i Mail.ru Group.

Vad mer att lÀsa om Àmnet:

  1. Mer Àn Ceph: blocklagring av MCS-molnet.
  2. Hur man vÀljer en databas för projektet sÄ att man inte behöver vÀlja igen..

KĂ€lla: habr.com

Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster