pornoporno izle
OpenVPN vždy a všade – 1. časť | BLACKHOLE.sk
webhosting by: WebSupport.sk                                             UnlimitedHosting | CustomHosting | FreeWeb.sk

OpenVPN vždy a všade – 1. časť

bwpow's picture

V nasledujúcich pár riadkoch sa rozpíšem o tom, ako som dostal netradičnú požiadavku a ako som sa s ňou vysporiadal. Nebude to ani tak technický návod, ako skôr rozprávanie o postupoch a problémoch, na ktoré som počas riešenia narazil a ktoré som musel prekonať. Všetko sa bude točiť okolo softvéru OpenVPN.

Naši klienti sú všelijakí. Niektorí najradšej vysedávajú v kancelárii a počítajú peniaze, iní zasa nepohrdnú kávičkou v kvalitnej kaviarni a ďalší neustále niekam cestujú. Skoro všetci ale chcú mať prístup k svojim firemným údajom, nech sa nachádzajú kdekoľvek. Poviete si, veď to je jednoduché. Dnes tu máme cloud, ktorý na nás vyskakuje na každom rohu. Rôzne spoločnosti sa predháňajú v tom, kto dokáže efektívnejšie získať prístup k vaším dôverným údajom a čo najlepšie ich využiť vo svoj prospech. No našťastie, u mnohých z mojich klientov prevláda zdravý rozum a cenu informácií si plne uvedomujú. Preto ich zaujíma bezpečnosť a dokonca sú ochotní za ňu aj zaplatiť. Neviem ktorý klient prvý požiadal o danú službu, ale čoskoro ju požadovali všetci.

Chcú spôsob, ako sa dostať k svojím dátam, nech sú kdekoľvek, na akomkoľvek internetovom pripojení, v akejkoľvek krajine a hlavne chcú, aby to bolo bezpečné. Chcú proste VPN. Myslím, že toto je vhodné miesto na malú poznámku. Keď píšem o dátach, nemyslím tým len súbory na nejakých zdielaných diskoch. Medzi dáta patrí aj SIP komunikácia, prístup ku kamerovým systémom a ku všemožným intranetovým aplikáciám. Rozhodol som sa im vyhovieť a dať im to, čo žiadajú. Ako nástroj som zvolil práve OpenVPN, lebo len ten poznám ako-tak dobre a narozdiel od rôznych uzavretých riešení mu aj trochu dôverujem.

Konkrétne požiadavky vyzerali teda nasledovne:

  • má zvládnuť obrovský nápor súčasne pripojených klientov, rádovo v stovkách
  • vytvoriť VPN server, na ktorý sa bude dať dostať aj z veľmi reštriktívneho internetového pripojenia
  • na pripojenie sa musí dať využiť klasický klientský softvér, takže žiadne prekompilovávanie neprichádza v úvahu
  • keďže nových klientov ma zvládnuť pripojiť aj cvičená opica, generovanie certifikátov pre jednotlivých klientov nie je možné (aj keď niektorí samostatný certifikát mať môžu)
  • niektoré služby sa nevedia spamätať z recyklovanej IP adresy (teda ak nejaký klient dostane adresu, ktorú predtým používal niekto iný), preto treba zabezpečiť to, aby klienti dostali stále tú istú, prípadne už veľmi dávno nepoužitú adresu
  • niektorí klienti majú vedieť medzi sebou komunikovať, iní nie

Ak ste už niekedy nastavovali OpenVPN server, tak viete, že splniť všetky tieto požiadavky nie je vôbec jednoduché. Mne sa to našťastie podarilo. Ako? Čítajte ďalej.

Ako zvládnuť obrovský nápor?
Služba OpenVPN beží len v jednom vlákne, čo veľmi nepoteší ľudí s viacjadrovými procesormi. Riešenie je našťastie jednoduché. Stačí spustiť viac serverových procesov súčasne a nejakým spôsobom prinútiť každého klienta, aby sa pripojil na jeden (náhodný) z nich. To sa dá spraviť viacerými spôsobmi.

Asi najčastejšie sa na tento účel používa direktíva remote-random v konfigurácii klienta. Následne stačí zadefinovať viac položiek server a pri pripájaní bude vybratá náhodná z nich. Tento spôsob ale nebol vyhovujúci pre moje nasadenie a tak som musel zvoliť iné riešenie. Nakoniec som si pomohol vďaka iptables a konkrétne modulu statistics. Jeden z módov tohto modulu, konkrétne mód random, umožňuje definovať pravdepodobnosť, s akou sa dané pravidlo vykoná.

Nech máme procesor so štyrmi jadrami a preto použijeme štyri serverové procesy, každý bežiaci na inom porte. Chceme teda napísať pravidlá tak, aby sa prichádzajúce nové spojenia rozdelili medzi tieto štyri bežiace procesy rovnomerne. Keď si vyhľadáte diskusné fóra a návody, kde sa použitie modulu random preberá, nájdete niečo v zmysle: „ak chcete, aby sa spojenia rovnomerne rozdelili, tak definujte každému pravidlu pravdepodobnosť 0.25“, čo je samozrejme nehorázna hlúposť. Treba si uvedomiť, že pravidlá sa v iptables nevyhodnocujú súčasne, ale jedno za druhým. Ako by vlastne dopadol prípad, keby ste mali štyri pravidlá za sebou a každé malo 25%-nú pravdepodobnosť, že bude vykonané? Uvažujme. Prvé pravidlo odkusne jednu štvrtinu prichádzajúcich pripojení, teda 3/4 postúpia ďalej. Druhé odkusne štvrtinu z týchto 3/4 a ďalej postúpi 9/16. A tak ďalej, až sa dostaneme k poslednému pravidlu, ktoré odkusne opäť štvrtinu a zvyšok spadne úplne mimo. Ako vidno, nerobí to to, čo sme chceli.

Aby rozdelenie bolo naozaj rovnomerné (v rámci možností), musí byť prvé pravidlo definované s pravdepodobnosťou 0.25, teda získa štvrtinu pripojení. Druhé ale už musí mať pravdepodobnosť 0.33 periodických, lebo po prvom pravidle sem prešli 3/4 pripojení, no my chceme, aby tu skončilo 1/4 zo všetkých, nie len z postupivších. A naozaj, ak vynásobíme 3/4 * 1/3 (pozdravujem Christii), tak dostaneme 1/4. Ďalšie pravidlo musí mať pravdepodobnosť 0.5 a posledné 1.

Dá sa na to celé ísť aj úplne intuitívne. Ak máme len jedno pravidlo, tak to musí logicky zahrnúť všetky pripojenia. Ak máme pravidlá dve, tak to prvé vie, že za ním ešte jedno nasleduje, takže si musí uchmatnúť polovicu pripojení a druhú polovicu prenechať poslednému pravidlu. Ak máme pravidlá tri, tak to prvé vie, že dve za ním nasledujú. Musí preto prijať jednu tretinu pripojení a zvyšok prenechať pre ďalšie dve pravidlá, aby si to už rovnako podelili. Ak sú štyri, tak prvé vie, že jedna štvrtina pripojení je jeho a zvyšok si musia ostatné pravidlá podeliť rovnomerne. A takto sa dá postupovať stále ďalej a ďalej. Vždy nás teda zaujíma len to, koľko pravidiel za tým ktorým nasleduje a vyhradiť pre neho rovnú časť tak, aby všetkým zvyšným zostala presne taká istá veľká časť.

Je celkom možné, že takýmto zdĺhavým rozoberaním triviálnych matematických princípov niektorých čitateľov urážam a oberám o ich drahocenný čas, no empiricky mám overené, že ani prírodovedecky vysokoškolsky vzdelaní ľudia si nevedeli s týmto problémom poradiť. Z tohto dôvodu som sa rozhodol predchádzajúcu stať zaradiť. Samotné fóra, roztrúsené po internete, ma v jej potrebnosti utvrdzujú.

Pravidlá teda môžu vyzerať nejako nasledovne:

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 1194 -m state --state NEW -m statistic --mode random --probability 0.25 -j REDIRECT --to 1201
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 1194 -m state --state NEW -m statistic --mode random --probability 0.3333 -j REDIRECT --to 1202
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 1194 -m state --state NEW -m statistic --mode random --probability 0.5 -j REDIRECT --to 1203
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 1194 -m state --state NEW -j REDIRECT --to 1204

Samozrejme, predpokladá sa, že eth0 je vonkajšie rozhranie, klienti sa pripájajú na port 1194/tcp a jednotlivé serverové procesy počúvajú na portoch 1201 až 1204.

Ako byť dostupný odvšadiaľ?
Mnohí mobilní používatelia často nevedia ovplyvniť kvalitu internetového pripojenia, na ktorom sa na svojich cestách ocitnú. Bojovať proti vysokej latencii alebo nízkej prenosovej rýchlosti na strane servera veľmi nemôžeme. Môžeme ale pomôcť aspoň pri reštriktívnom pripojení. Na mnohých verejných sieťach sa človek môže stretnúť s blokovaním rôznych portov. Často je to skoro celé UDP, inokedy sú zasa povolené len porty 80 a 443 na TCP, aj to len cez nejaké proxy. Preto je dobré mať server počúvajúci ideálne na čo najväčšom počte rôznych portov a protokolov. Po rokoch prevádzkovania rôznych VPN a iných pripojení som dokonvergoval k nasledujúcemu zoznamu, ktorý sa pretlačí skoro vždy.

fw_ports="123/udp 161/udp 53/udp 443/tcp 80/tcp 993/tcp 995/tcp 110/tcp 143/tcp 21/tcp"

V tomto poradí sa pokúša pripájať každý klient. Na predných priečkach sa nachádza UDP a ak všetky tri porty zlyhajú, nasledujú klasické TCP porty. Keďže OpenVPN balí všetku komunikáciu do klasického SSL, prejde pripojenie na porte 443/tcp aj cez dosť prísne L7 firewally.

Serverový proces OpenVPN sa žiaľ nedá nastaviť tak, aby súčasne počúval na TCP aj UDP, preto mám na strane servera niekoľko (podľa počtu jadier) procesov počúvajúcich na UDP a rovnaký počet procesov počúvajúcich na TCP.

Skript, ktorý vygeneruje pravidlá pre všetko popísané v týchto dvoch kapitolách, môže vyzerať nasledovne:

port_begin="5131"
port_num="4"
protos="udp tcp"
fw_ports="53/udp 123/udp 161/udp 443/tcp 80/tcp 993/tcp 995/tcp 110/tcp 143/tcp 21/tcp"
fw_file="/tmp/rapid-vpn.firewall"
local_if="eth0"
local_ip="A.B.C.D"
FNAME="$fw_file"
echo "#!/bin/bash" > "$FNAME"
echo "# Generated on $(date)" >> "$FNAME"
port="$port_begin"
for proto in $protos; do
  if [ "$proto" != "udp" ] && [ "$proto" != "tcp" ]; then myexit 1 "Proto must be 'tcp' or 'udp'"; fi
  echo "" >> "$FNAME"
  echo "# INPUT $proto" >> "$FNAME"
  let "out_port=port+port_num-1"
  echo "\$IPTABLES -A INPUT -p $proto -i $local_if -d $local_ip --dport ${port}:${out_port} -m state --state NEW -j ACCEPT" >> "$FNAME"
  echo "" >> "$FNAME"
  echo "# DNAT $proto" >> "$FNAME"
  for X in $fw_ports; do
    read in_port in_proto <<<$(IFS='/'; echo $X)
    if [ "$in_proto" == "$proto" ] && [[ $in_port =~ '^[0-9]+$' ]]; then
      echo "# ${in_port}/${in_proto}" >> "$FNAME"
      for I in $(seq 1 $port_num); do
        let "out_port=port+I-1"
        if [ "$I" -gt "1" ]; then
          PROB=$(awk "BEGIN{print 1.0 / $I}")
          echo "\$IPTABLES -t nat -I PREROUTING -i $local_if -d $local_ip -p $proto --dport $in_port -m state --state NEW -m statistic --mode random --probability $PROB -j DNAT --to ${local_ip}:${out_port}" >> "$FNAME"
        else
          echo "\$IPTABLES -t nat -I PREROUTING -i $local_if -d $local_ip -p $proto --dport $in_port -m state --state NEW -j DNAT --to ${local_ip}:${out_port}" >> "$FNAME"
        fi
      done
    fi
  done
  let "port=port+port_num"
done

Po vygenerovaní stačí súbor s pravidlami zavolať pri zavádzaní firewallu a všetko by malo pekne fungovať. Po pár hodinách môžu štatistiky vyzerať napríklad nejako takto:

iptables -t nat -vnL
Chain PREROUTING (policy ACCEPT 468K packets, 167M bytes)
pkts bytes target    prot opt in    out    source              destination
  28  1580 DNAT      tcp  --  eth0  *      0.0.0.0/0            A.B.C.D        tcp dpt:80 state NEW statistic mode random probability 0.250000 to:A.B.C.D:5138
  26  1508 DNAT      tcp  --  eth0  *      0.0.0.0/0            A.B.C.D        tcp dpt:80 state NEW statistic mode random probability 0.333333 to:A.B.C.D:5137
  24  1376 DNAT      tcp  --  eth0  *      0.0.0.0/0            A.B.C.D        tcp dpt:80 state NEW statistic mode random probability 0.500000 to:A.B.C.D:5136
  30  1720 DNAT      tcp  --  eth0  *      0.0.0.0/0            A.B.C.D        tcp dpt:80 state NEW to:A.B.C.D:5135
    5  276 DNAT      tcp  --  eth0  *      0.0.0.0/0            A.B.C.D        tcp dpt:443 state NEW statistic mode random probability 0.250000 to:A.B.C.D:5138
    3  152 DNAT      tcp  --  eth0  *      0.0.0.0/0            A.B.C.D        tcp dpt:443 state NEW statistic mode random probability 0.333333 to:A.B.C.D:5137
    4  212 DNAT      tcp  --  eth0  *      0.0.0.0/0            A.B.C.D        tcp dpt:443 state NEW statistic mode random probability 0.500000 to:A.B.C.D:5136
    3  168 DNAT      tcp  --  eth0  *      0.0.0.0/0            A.B.C.D        tcp dpt:443 state NEW to:A.B.C.D:5135
  26 18053 DNAT      udp  --  eth0  *      0.0.0.0/0            A.B.C.D        udp dpt:161 state NEW statistic mode random probability 0.250000 to:A.B.C.D:5134
  37 24610 DNAT      udp  --  eth0  *      0.0.0.0/0            A.B.C.D        udp dpt:161 state NEW statistic mode random probability 0.333333 to:A.B.C.D:5133
  35 24423 DNAT      udp  --  eth0  *      0.0.0.0/0            A.B.C.D        udp dpt:161 state NEW statistic mode random probability 0.500000 to:A.B.C.D:5132
  29 18890 DNAT      udp  --  eth0  *      0.0.0.0/0            A.B.C.D        udp dpt:161 state NEW to:A.B.C.D:5131
  22 15720 DNAT      udp  --  eth0  *      0.0.0.0/0            A.B.C.D        udp dpt:123 state NEW statistic mode random probability 0.250000 to:A.B.C.D:5134
  25 17389 DNAT      udp  --  eth0  *      0.0.0.0/0            A.B.C.D        udp dpt:123 state NEW statistic mode random probability 0.333333 to:A.B.C.D:5133
  29 18371 DNAT      udp  --  eth0  *      0.0.0.0/0            A.B.C.D        udp dpt:123 state NEW statistic mode random probability 0.500000 to:A.B.C.D:5132
  22 15608 DNAT      udp  --  eth0  *      0.0.0.0/0            A.B.C.D        udp dpt:123 state NEW to:A.B.C.D:5131

Serverové procesy počúvajú teda na UDP portoch 5131 až 5134 a na TCP portoch 5135 až 5138.

Ako ale zabezpečiť zvyšné podmienky? Ako klientovi prideliť stále tú istú adresu, nech sa pripojí akýmkoľvek protokolom? Ako sa vysporiadať s klientmi s rovnakými certifikátmi a neprideliť im adresu, ktorú mal niekto predtým? Dozviete sa v druhej, záverečnej časti.

Average rating
(9 votes)

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
matej's picture

Re: OpenVPN vždy a všade – 1. časť

Pekne riesenie, osobne by som ale pouzil iptables podtabulky pre kazdy port zvlast a volal ich cez -j, aby paket nemusel by matchovany cez 4*N pravidiel. A podla poctu tych portov mozno este zabalit do dalsej tabulky a tu zavolat cez multiport. (Len taky detail, vykonovo to asi nijak sialene nepomoze ked este stale potrebuju spracovat v aplikacii, ale zbavis sa rychlejsie ostatnych paketov ktore nematchnu nic z toho.)

bwpow's picture

Re: OpenVPN vždy a všade – 1. časť

Ano, tak by to bolo asi naozaj lepsie, ale osobne mam trochu averziu proti tomu, kedze potom sa neda pouzit jednoduche iptables -F :) Nastastie, v tomto pripade tych pravidiel je naozaj len zopar.

Prisiel som, videl som, hmm...

matej's picture

Re: OpenVPN vždy a všade – 1. časť

Myslim, ze toto by mohlo fungovat:

# Flush all rules
$IPT -F
$IPT -t nat -F
$IPT -t mangle -F
# Erase all non-default chains
$IPT -X
$IPT -t nat -X
$IPT -t mangle -X

bwpow's picture

Re: OpenVPN vždy a všade – 1. časť

O tom -X som nevedel. Vdaka.

Kedysi davno som hladal, ako to spravit a musel som to prehliadnut v man-e. Odvtedy pouzivam bashovsky one-liner a nenapadlo mi pozriet do manualu opat :) Esteze tu mame blackhole. Nech si hovori kto chce co chce, ale na tomto webe a prilahlom IRC som sa dozvedel omnoho viac uzitocnych informacii ako kdekolvek inde.

Prisiel som, videl som, hmm...

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
webhosting by: WebSupport.sk UnlimitedHosting | CustomHosting | FreeWeb.sk