Ako ExpressVPN udržuje svoje webové servery opravené a zabezpečené

Server ExpressVPN vychádza z popola.

Tento článok vysvetľuje prístup ExpressVPN k správa bezpečnostných opráv pre infraštruktúru prevádzkujúcu webovú stránku ExpressVPN (nie servery VPN). Náš prístup k bezpečnosti je vo všeobecnosti:

  1. Robte systémy veľmi ťažko sa hackne.
  2. Minimalizujte možné poškodenie ak sa systém hypoteticky hackne a uznáva skutočnosť, že niektoré systémy sa nedajú dokonale zabezpečiť. Zvyčajne sa to začína vo fáze architektonického návrhu, kde minimalizujeme prístup aplikácie.
  3. Minimalizujte množstvo času že systém môže zostať ohrozený.
  4. Potvrdiť tieto body majú pravidelné interné aj externé pätky.

Bezpečnosť je zakorenená v našej kultúre a je hlavným záujmom, ktorým sa riadi všetka naša práca. Existuje mnoho ďalších tém, ako sú naše postupy vývoja bezpečnostného softvéru, zabezpečenie aplikácií, zamestnanecké procesy a školenia atď., Ale tie sú mimo rozsah tohto príspevku..

Tu vysvetlíme, ako dosahujeme nasledujúce ciele:

  1. Skontrolujte, či sú všetky servery úplne opravené a nikdy viac ako 24 hodín za uverejnením CVE.
  2. Zaistite, aby sa žiadny server nepoužíva dlhšie ako 24 hodín, čím sa stanoví horná hranica času, ktorý môže útočník vytrvať.

Oba ciele dosahujeme prostredníctvom automatizovaný systém, ktorý obnovuje servery, počnúc OS a všetkými najnovšími opravami a ničí ich najmenej raz za 24 hodín.

Naším zámerom pre tento článok je byť užitočný pre ostatných vývojárov, ktorí čelia podobným výzvam, a poskytnúť zákazníkom a médiám prehľad o fungovaní ExpressVPN..

Ako používame možné príručky a službu Cloudformation

Webová infraštruktúra ExpressVPN je hosťovaná na serveri AWS (na rozdiel od našich serverov VPN, ktoré fungujú na vyhradenom hardvéri) a ich funkcie využívame na to, aby sme ich mohli znova vybudovať.

Celá naša webová infraštruktúra je vybavená technológiou Cloudformation a snažíme sa automatizovať čo najviac procesov. Zistili sme však, že práca so surovými šablónami Cloudformation je dosť nepríjemná z dôvodu potreby opakovania, celkovo slabej čitateľnosti a obmedzení syntaxe JSON alebo YAML..

Aby sme to zmiernili, používame DSL s názvom cloudformation-ruby-dsl, ktorý nám umožňuje písať definície šablón v Ruby a exportovať šablóny Cloudformation v JSON.

Konkrétne, DSL nám umožňuje písať skripty užívateľských údajov ako bežné skripty, ktoré sa automaticky prevádzajú na JSON (a neprechádzajú bolestivým procesom premeny každého riadka skriptu na platný reťazec JSON).

Všeobecná úloha, ktorá sa nazýva cloudformačná infraštruktúra, sa stará o vykreslenie aktuálnej šablóny do dočasného súboru, ktorý potom použije modul Možné cloudformácie:

- name: 'render {{component}} cloudformation stack json'
shell: 'rubín "{{template_name | predvolený (komponent)}}" rozbaliť - stack-name {{stack}} --region {{aws_region}} > {{tempfile_path}} '
args:
chdir: ../cloudformation/templates
zmenené_kedy: nepravdivé

- name: 'create / update {{component}} stack'
cloudformation:
stack_name: '{{stack}} - {{xv_env_name}} - {{component}}'
stav: prítomný
región: '{{aws_region}}'
template: '{{tempfile_path}}'
template_parameters: '{{template_parameters | predvolené ({})}} '
stack_policy: '{{stack_policy}}'
register: cf_result

V príručke hrajeme úlohu cloudformation-infrastructure niekoľkokrát s rôznymi premennými komponentov, aby sme vytvorili niekoľko stohov Cloudformation. Napríklad máme sieťový zásobník, ktorý definuje VPC a súvisiace zdroje, a zásobník aplikácií, ktorý definuje skupinu Automatické prispôsobenie, spustenie konfigurácie, háky životného cyklu atď..

Potom použijeme trochu škaredý, ale užitočný trik na premenu výstupu modulu cloudformácie na možné premenné pre nasledujúce úlohy. Tento prístup musíme použiť, pretože funkcia Ansible neumožňuje vytváranie premenných s dynamickými názvami:

- zahŕňajú: _tempfile.yml
- kópia:
obsah: '{{komponent | regex_replace ("-", "_")}} _ stack: {{cf_result.stack_outputs | to_json}} '
dest: '{{tempfile_path}}. json'
no_log: true
zmenené_kedy: nepravdivé

- include_vars: '{{tempfile_path}}. json'

Aktualizácia skupiny EC2 Auto Scaling

Webové stránky ExpressVPN sú hostené na viacerých inštanciách EC2 v skupine Auto Scaling za nástrojom Application Load Balancer, ktorý nám umožňuje zničiť servery bez akýchkoľvek prestojov, pretože nástroj balancer môže vyčerpať existujúce pripojenia pred ukončením inštancie..

Cloudformation organizuje celú prestavbu a my spúšťame Príručnú príručku opísanú vyššie každých 24 hodín na prebudovanie všetkých inštancií pomocou atribútu AutoScalingRollingUpdate UpdatePolicy zdroja AWS :: AutoScaling :: AutoScalingGroup.

Keď sa jednoducho spúšťa opakovane bez akýchkoľvek zmien, atribút UpdatePolicy sa nepoužíva - vyvoláva sa iba za osobitných okolností, ako je opísané v dokumentácii. Jednou z týchto okolností je aktualizácia konfigurácie spustenia automatického škálovania - šablóny, ktorú skupina automatického škálovania používa na spúšťanie inštancií EC2 - ktorá obsahuje skript používateľských údajov EC2, ktorý sa spúšťa pri vytváraní novej inštancie:

zdroj 'AppLaunchConfiguration', Typ: 'AWS :: AutoScaling :: LaunchConfiguration',
Vlastnosti: {
KeyName: param ('AppServerKey'),
ImageId: param („AppServerAMI“),
InstanceType: param ('AppServerInstanceType'),
SecurityGroups: [
param ( 'SecurityGroupApp'),
],
IamInstanceProfile: param ('RebuildIamInstanceProfile'),
Sledovanie inštancií: true,
BlockDeviceMappings: [
{
Názov zariadenia: '/ dev / sda1', # koreňový zväzok
Ebs: {
VolumeSize: param („AppServerStorageSize“),
VolumeType: param ('AppServerStorageType'),
DeleteOnTermination: true,
},
},
],
UserData: base64 (interpolovať (súbor ('scripts / app_user_data.sh')))),
}

Ak vykonáme akúkoľvek aktualizáciu skriptu s používateľskými údajmi, dokonca aj komentár, bude konfigurácia spustenia považovaná za zmenenú a Cloudformation aktualizuje všetky inštancie v skupine Auto Scaling, aby vyhovovala novej konfigurácii spustenia..

Vďaka cloudformation-ruby-dsl a jeho funkcii interpolácie môžeme použiť referencie Cloudformation v skripte app_user_data.sh:

readonly rebuild_timestamp ="{{param ('RebuildTimestamp')}}"

Táto procedúra zaisťuje, že naša spúšťacia konfigurácia je nová pri každom spustení obnovy.

Háky na životný cyklus

Používame háčiky životného cyklu Auto Scaling, aby sme sa ubezpečili, že naše inštancie sú plne zabezpečené a pred uvedením do prevádzky absolvujú požadované zdravotné kontroly..

Použitie háčikov životného cyklu nám umožňuje mať rovnaký životný cyklus inštancie, keď spustíme aktualizáciu pomocou funkcie Cloudformation, aj keď dôjde k automatickej zmene mierky (napríklad keď inštancia zlyhá pri kontrole stavu EC2 a bude ukončená). Nepoužívame cfn-signal a pravidlá aktualizácie automatického prispôsobovania WaitOnResourceSignals, pretože sa používajú iba vtedy, keď Cloudformation spustí aktualizáciu..

Keď skupina na automatické škálovanie vytvorí novú inštanciu, spustí sa háčik životného cyklu EC2_INSTANCE_LAUNCHING a automaticky uvedie inštanciu do stavu Čakajúce: čakanie.

Keď je inštancia plne nakonfigurovaná, začne biť do svojich vlastných koncových bodov kontroly stavu skrútením zo skriptu užívateľských údajov. Keď kontroly stavu nahlásia aplikáciu ako zdravú, vydáme akciu POKRAČOVAŤ pre tento hák životného cyklu, takže inštancia sa pripojí k vyvažovači záťaže a začne obsluhovať premávku.

Ak zdravotné kontroly zlyhajú, vydáme akciu ABANDON, ktorá ukončí chybnú inštanciu a skupina na automatické prispôsobenie stupnice spustí ďalšiu..

Okrem zlyhania úspešného vykonania zdravotných kontrol môže zlyhať skript našich používateľských údajov aj v iných bodoch - napríklad ak dočasné problémy s pripojením bránia inštalácii softvéru..

Chceme, aby vytvorenie nového prípadu zlyhalo, len čo si uvedomíme, že to nikdy nebude zdravé. Aby sme to dosiahli, nastavíme pascu ERR v skripte užívateľských údajov spolu s set -o errtrace, aby sme zavolali funkciu, ktorá odošle akciu životného cyklu ABANDON, takže chybná inštancia sa môže čo najskôr ukončiť..

Skripty údajov používateľov

Skript užívateľských údajov je zodpovedný za inštaláciu všetkého požadovaného softvéru do inštancie. Úspešne sme použili možnosť poskytovať inštancie a spoločnosť Capistrano nasadila aplikácie na dlhú dobu, takže ich tiež používame tu, čo umožňuje minimálny rozdiel medzi pravidelnými nasadeniami a prestavbami..

Skript užívateľských údajov skontroluje náš archív aplikácií od spoločnosti Github, ktorý obsahuje skripty Možné zabezpečenie, potom spustí Ansible a Capistrano ukázal na localhost.

Pri odhlasovaní kódu musíme mať istotu, že sa pri opätovnom zostavení nasadí aktuálne nasadená verzia aplikácie. Skript nasadenia Capistrano obsahuje úlohu, ktorá aktualizuje súbor v S3, v ktorom je uložený aktuálne nasadený potvrdzovací SHA. Keď dôjde k prebudovaniu, systém vyzdvihne potvrdenie, ktoré sa má nasadiť z tohto súboru.

Aktualizácie softvéru sa vykonávajú spustením bezobslužnej aktualizácie v popredí pomocou príkazu bezobslužnej aktualizácie. Po dokončení sa inštancia reštartuje a spustí kontrolu stavu.

Zaobchádzanie so tajomstvami

Server potrebuje dočasný prístup k tajomstvám (ako napríklad k heslu možného úschovne), ktoré sa načítajú z pamäte parametrov EC2. Server môže počas prestavby pristupovať k tajomstvám iba na krátku dobu. Po ich načítaní okamžite nahradíme počiatočný profil inštancie iným profilom, ktorý má prístup iba k prostriedkom, ktoré sú potrebné na spustenie aplikácie..

Chceme sa vyhnúť ukladaniu akýchkoľvek tajomstiev do trvalej pamäte inštancie. Jediným tajomstvom, ktoré ukladáme na disk, je kľúč Github SSH, ale nie jeho prístupová fráza. Neukladáme ani heslo do trezora.

Tieto prístupové frázy však musíme preniesť do SSH a Ansible, a to je možné iba v interaktívnom režime (tj pomôcka vyzve používateľa, aby zadal prístupové frázy manuálne) z dobrého dôvodu - ak je prístupová fráza súčasťou príkazu, je uložené v histórii shellu a môžu byť viditeľné pre všetkých používateľov v systéme, ak spustia ps. Na automatizáciu interakcie s týmito nástrojmi používame nástroj očekávania:

očakávať << EOF
cd $ {repo_dir}
spawn make ansible_local env = $ {deploy_env} stack = $ {stack} hostname = $ {server_hostname}
nastaviť časový limit 2
očakávať „heslo trezora“
send "$ {Vault_password} \ r"
nastaviť časový limit 900
očakávať {
"nedosiahnuteľné = 0 zlyhalo = 0" {
výstup 0
}
eof {
výstup 1
}
čas vypršal {
výstup 1
}
}
EOF

Spustenie obnovy

Keďže spustenie obnovy spustíme pomocou rovnakého skriptu Cloudformation, ktorý sa používa na vytvorenie / aktualizáciu našej infraštruktúry, musíme sa ubezpečiť, že náhodne neaktualizujeme časť infraštruktúry, ktorá sa počas prestavby nemá aktualizovať..

Dosahujeme to stanovením obmedzujúcich pravidiel pre zásobníky v našich komároch Cloudformation, takže sa aktualizujú iba zdroje potrebné na opätovnú výstavbu:

{
"výkaz" : [
{
"účinok" : "dovoliť",
"akčné" : "Aktualizácia: Upraviť",
"hlavná": "*",
"prostriedky" : [
"LogicalResourceId / * AutoScalingGroup"
] },
{
"účinok" : "dovoliť",
"akčné" : "Aktualizovať: Nahradiť",
"hlavný": "*",
"prostriedky" : [
"LogicalResourceId / * LaunchConfiguration"
] }
] }

Ak potrebujeme vykonať skutočné aktualizácie infraštruktúry, musíme manuálne aktualizovať politiku zásobníkov, aby bolo možné tieto zdroje výslovne aktualizovať.

Pretože sa názvy našich serverov a adresy IP menia každý deň, máme skript, ktorý aktualizuje naše miestne možné zásoby a konfigurácie SSH. Objavuje inštancie prostredníctvom rozhrania AWS API pomocou značiek, vykresľuje inventárne a konfiguračné súbory zo šablón ERB a pridáva nové adresy IP do SSH known_hosts.

ExpressVPN dodržiava najvyššie bezpečnostné štandardy

Prestavba serverov nás chráni pred špecifickou hrozbou: útočníci získavajú prístup k našim serverom prostredníctvom zraniteľnosti jadra / softvéru.

Je to však iba jeden z mnohých spôsobov, ako udržiavať našu infraštruktúru v bezpečí, okrem iného aj pravidelné pravidelné bezpečnostné audity a neprístupnosť kritických systémov z internetu..

Ďalej zabezpečujeme, aby všetky naše kódy a interné procesy dodržiavali najvyššie bezpečnostné štandardy.

Ako ExpressVPN udržuje svoje webové servery opravené a zabezpečené
admin Author
Sorry! The Author has not filled his profile.