Hvernig við hjá ZeroTech tengdum Apple Safari og viðskiptavinavottorð við nettengi

Greinin mun nýtast þeim sem:

  • veit hvað viðskiptamannavottorð er og skilur hvers vegna það þarf nettengi í Safari fyrir farsíma;
  • Mig langar til að birta vefþjónustur fyrir takmarkaðan hóp fólks eða aðeins sjálfum mér;
  • heldur að allt hafi þegar verið gert af einhverjum og vill gera heiminn aðeins þægilegri og öruggari.

Saga vefsokkanna hófst fyrir um 8 árum síðan. Áður voru aðferðir notaðar í formi langra http-beiðna (reyndar svör): vafri notandans sendi beiðni til netþjónsins og beið eftir að hann svaraði einhverju, eftir svarið tengdist hann aftur og beið. En svo birtust veftenglar.

Hvernig við hjá ZeroTech tengdum Apple Safari og viðskiptavinavottorð við nettengi

Fyrir nokkrum árum síðan þróuðum við okkar eigin útfærslu í hreinu PHP, sem getur ekki notað https beiðnir, þar sem þetta er tenglalagið. Ekki alls fyrir löngu lærðu næstum allir netþjónar að proxy-beiðnir í gegnum https og styðja tengingu: uppfærslu.

Þegar þetta gerðist urðu websockets nánast sjálfgefin þjónusta fyrir SPA forrit, því hversu þægilegt það er að útvega efni til notandans að frumkvæði þjónsins (senda skilaboð frá öðrum notanda eða hlaða niður nýrri útgáfu af mynd, skjali, kynningu sem einhver annar er að breyta) .

Þrátt fyrir að viðskiptavottorð hafi verið til í nokkuð langan tíma er það enn illa stutt, þar sem það skapar mörg vandamál þegar reynt er að komast framhjá því. Og (hugsanlega :slightly_smiling_face: ) þess vegna vilja IOS vafrar (allir nema Safari) ekki nota það og biðja um það frá staðbundinni vottorðaverslun. Vottorð hafa marga kosti samanborið við innskráningu/pass eða ssh lykla eða að loka nauðsynlegum höfnum í gegnum eldvegg. En það er ekki það sem þetta snýst um.

Í iOS er aðferðin við að setja upp skírteini frekar einföld (ekki án sérstakra), en almennt er það gert samkvæmt leiðbeiningum, sem það er mikið af á netinu og sem er aðeins fáanlegt fyrir Safari vafrann. Því miður veit Safari ekki hvernig á að nota Client Сert fyrir vefinnstungur, en það eru margar leiðbeiningar á netinu um hvernig eigi að búa til slíkt skírteini, en í reynd er þetta ekki hægt að ná.

Hvernig við hjá ZeroTech tengdum Apple Safari og viðskiptavinavottorð við nettengi

Til að skilja netstungur notuðum við eftirfarandi áætlun: vandamál/tilgáta/lausn.

Vandamál: það er enginn stuðningur við vefinnstungur þegar umboðsbeiðnir eru sendar til auðlinda sem eru verndaðar af biðlaravottorði í Safari farsímavafranum fyrir IOS og önnur forrit sem hafa virkjað vottorðsstuðning.

Tilgátur:

  1. Það er hægt að stilla slíka undantekningu til að nota skírteini (vitandi að þau verða engin) í veftengi innri/ytri umboðsaðfanga.
  2. Fyrir websockets geturðu búið til einstaka, örugga og verjanlega tengingu með því að nota tímabundnar lotur sem myndast við venjulega (ekki vefsocket) vafrabeiðni.
  3. Hægt er að útfæra tímabundnar lotur með því að nota einn proxy vefþjón (aðeins innbyggðar einingar og aðgerðir).
  4. Tímabundin lotumerki hafa þegar verið innleidd sem tilbúnar Apache einingar.
  5. Hægt er að útfæra tímabundna lotumerki með því að hanna samskiptauppbygginguna á rökréttan hátt.

Sýnilegt ástand eftir innleiðingu.

Hlutlæg: stjórnun þjónustu og innviða ætti að vera aðgengileg úr farsíma á IOS án viðbótarforrita (svo sem VPN), sameinuð og örugg.

Viðbótarmarkmið: spara tíma og fjármagn/símaumferð (sumar þjónustur án vefinnstunga búa til óþarfa beiðnir) með hraðari afhendingu efnis á farsímanetinu.

Hvernig á að athuga?

1. Opnunarsíður:

— например, https://teamcity.yourdomain.com в мобильном браузере Safari (доступен также в десктопной версии) — вызывает успешное подключение к веб-сокетам.
— например, https://teamcity.yourdomain.com/admin/admin.html?item=diagnostics&tab=webS…— показывает ping/pong.
— например, https://rancher.yourdomain.com/p/c-84bnv:p-vkszd/workload/deployment:danidb:ph…-> viewlogs — показывает логи контейнера.

2. Eða í stjórnborði þróunaraðila:

Hvernig við hjá ZeroTech tengdum Apple Safari og viðskiptavinavottorð við nettengi

Tilgátuprófun:

1. Það er hægt að stilla slíka undantekningu til að nota skírteini (vitandi að þau verða engin) í vefinnstungur af innri/ytri proxy-auðlindum.

2 lausnir fundust hér:

a) Á vettvangi

<Location sock*> SSLVerifyClient optional </Location>
<Location /> SSLVerifyClient require </Location>

breyta aðgangsstigi.

Þessi aðferð hefur eftirfarandi blæbrigði:

  • Staðfesting vottorðs á sér stað eftir beiðni til umboðsaðfangsins, það er að segja handabandi eftir beiðni. Þetta þýðir að umboðið mun fyrst hlaða og síðan loka beiðninni til vernduðu þjónustunnar. Þetta er slæmt, en ekki mikilvægt;
  • Í http2 samskiptareglunum. Það er enn í drögum og vafraframleiðendur vita ekki hvernig á að útfæra það #upplýsingar um tls1.3 http2 færsluhandabandi (virkar ekki núna) Innleiða RFC 8740 "Notkun TLS 1.3 með HTTP/2";
  • Ekki er ljóst hvernig á að sameina þessa vinnslu.

b) Á grunnstigi, leyfa ssl án vottorðs.

SSLVerifyClient require => SSLVerifyClient valfrjálst, en þetta dregur úr öryggisstigi proxy-þjónsins, þar sem slík tenging verður unnin án vottorðs. Hins vegar geturðu enn frekar neitað aðgangi að umboðsþjónustu með eftirfarandi tilskipun:

RewriteEngine        on
RewriteCond     %{SSL:SSL_CLIENT_VERIFY} !=SUCCESS
RewriteRule     .? - [F]
ErrorDocument 403 "You need a client side certificate issued by CAcert to access this site"

Nánari upplýsingar er að finna í greininni um ssl: Auðkenning Apache Server viðskiptavinarvottorðs

Báðir valkostir voru prófaðir, valkostur „b“ var valinn fyrir fjölhæfni hans og samhæfni við http2 samskiptareglur.

Til að ljúka við sannprófun þessarar tilgátu tók það margar tilraunir með uppsetninguna; eftirfarandi hönnun var prófuð:

ef = krefjast = endurskrifa

Niðurstaðan er eftirfarandi grunnhönnun:

SSLVerifyClient optional
RewriteEngine on
RewriteCond %{SSL:SSL_CLIENT_VERIFY} !=SUCCESS
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule     .? - [F]
#ErrorDocument 403 "You need a client side certificate issued by CAcert to access this site"

#websocket for safari without cert auth
<If "%{SSL:SSL_CLIENT_VERIFY} != 'SUCCESS'">
<If "%{HTTP:Upgrade} = 'websocket'">
...
    #замещаем авторизацию по владельцу сертификата на авторизацию по номеру протокола
    SSLUserName SSl_PROTOCOL
</If>
</If>

Að teknu tilliti til fyrirliggjandi heimildar frá eiganda skírteinisins, en með vottorð sem vantaði, þurfti ég að bæta við vottorðseiganda sem ekki var til í formi einnar af tiltækum breytum SSl_PROTOCOL (í stað SSL_CLIENT_S_DN_CN), nánari upplýsingar í skjölunum:

Apache Module mod_ssl

Hvernig við hjá ZeroTech tengdum Apple Safari og viðskiptavinavottorð við nettengi

2. Fyrir veftengi geturðu búið til einstaka, örugga og verndaða tengingu með því að nota tímabundnar lotur sem myndast við venjulega (ekki nettengi) vafrabeiðni.

Byggt á fyrri reynslu þarftu að bæta við viðbótarhluta við uppsetninguna til að útbúa tímabundna tákn fyrir vefinnstungutengingar meðan á venjulegri (ekki vefinnstungu) beiðni stendur.

#подготовка передача себе Сookie через пользовательский браузер
<If "%{SSL:SSL_CLIENT_VERIFY} = 'SUCCESS'">
<If "%{HTTP:Upgrade} != 'websocket'">
Header set Set-Cookie "websocket-allowed=true; path=/; Max-Age=100"
</If>
</If>

#проверка Cookie для установления веб-сокет соединения
<source lang="javascript">
<If "%{SSL:SSL_CLIENT_VERIFY} != 'SUCCESS'">
<If "%{HTTP:Upgrade} = 'websocket'">
#check for exists cookie

#get and check
SetEnvIf Cookie "websocket-allowed=(.*)" env-var-name=$1

#or rewrite rule
RewriteCond %{HTTP_COOKIE} !^.*mycookie.*$

#or if
<If "%{HTTP_COOKIE} =~ /(^|; )cookie-names*=s*some-val(;|$)/ >
</If

</If>
</If>

Prófanir sýndu að það virkar. Það er hægt að flytja vafrakökur yfir á sjálfan þig í gegnum vafra notandans.

3. Hægt er að útfæra tímabundna fundi með því að nota einn proxy vefþjón (aðeins innbyggðar einingar og aðgerðir).

Eins og við komumst að áðan hefur Apache töluvert af kjarnavirkni sem gerir þér kleift að búa til skilyrtar smíði. Hins vegar þurfum við aðferðir til að vernda upplýsingarnar okkar á meðan þær eru í vafra notandans, svo við komumst að því hvað á að geyma og hvers vegna, og hvaða innbyggðu aðgerðir við munum nota:

  • Við þurfum tákn sem ekki er auðvelt að afkóða.
  • Við þurfum tákn sem hefur úreldingu innbyggt í það og getu til að athuga úreldingu á þjóninum.
  • Við þurfum tákn sem verður tengt eiganda skírteinisins.

Þetta krefst kjötkássaaðgerðar, salts og dagsetningar til að elda táknið. Byggt á skjölunum Tjáning í Apache HTTP Server við höfum þetta allt út úr kassanum sha1 og %{TIME}.

Útkoman var þessi hönnun:

#нет сертификата, и обращение к websocket
<If "%{SSL:SSL_CLIENT_VERIFY} != 'SUCCESS'">
<If "%{HTTP:Upgrade} = 'websocket'">
    SetEnvIf Cookie "zt-cert-sha1=([^;]+)" zt-cert-sha1=$1
    SetEnvIf Cookie "zt-cert-uid=([^;]+)" zt-cert-uid=$1
    SetEnvIf Cookie "zt-cert-date=([^;]+)" zt-cert-date=$1

#только так можно работать с переменными, полученными в env-ах в этот момент времени, более они нигде не доступны для функции хеширования (по отдельности можно, но не вместе, да и ещё с хешированием)
    <RequireAll>
        Require expr %{sha1:salt1%{env:zt-cert-date}salt3%{env:zt-cert-uid}salt2} == %{env:zt-cert-sha1}
        Require expr %{env:zt-cert-sha1} =~ /^.{40}$/
    </RequireAll>
</If>
</If>

#есть сертификат, запрашивается не websocket
<If "%{SSL:SSL_CLIENT_VERIFY} = 'SUCCESS'">
<If "%{HTTP:Upgrade} != 'websocket'">
    SetEnvIf Cookie "zt-cert-sha1=([^;]+)" HAVE_zt-cert-sha1=$1

    SetEnv zt_cert "path=/; HttpOnly;Secure;SameSite=Strict"
#Новые куки ставятся, если старых нет
    Header add Set-Cookie "expr=zt-cert-sha1=%{sha1:salt1%{TIME}salt3%{SSL_CLIENT_S_DN_CN}salt2};%{env:zt_cert}" env=!HAVE_zt-cert-sha1
    Header add Set-Cookie "expr=zt-cert-uid=%{SSL_CLIENT_S_DN_CN};%{env:zt_cert}" env=!HAVE_zt-cert-sha1
    Header add Set-Cookie "expr=zt-cert-date=%{TIME};%{env:zt_cert}" env=!HAVE_zt-cert-sha1
</If>
</If>

Markmiðinu hefur verið náð, en vandamál eru með úreldingu netþjóna (hægt er að nota ársgamla köku), sem þýðir að táknin, þó að þau séu örugg fyrir innri notkun, eru óörugg til iðnaðar (fjölda)notkunar.

Hvernig við hjá ZeroTech tengdum Apple Safari og viðskiptavinavottorð við nettengi

4. Tímabundin lotumerki hafa þegar verið innleidd sem tilbúnar Apache einingar.

Eitt verulegt vandamál var eftir frá fyrri endurtekningu - vanhæfni til að stjórna táknöldrun.

Við erum að leita að tilbúinni einingu sem gerir þetta, samkvæmt orðunum: apache token json two factor auth

Já, það eru til tilbúnar einingar, en þær eru allar bundnar við sérstakar aðgerðir og hafa gripi í formi þess að hefja lotu og viðbótarkökur. Það er að segja ekki um stund.
Það tók okkur fimm tíma að leita, sem gaf ekki ákveðna niðurstöðu.

5. Hægt er að útfæra tímabundna lotumerki með því að hanna uppbyggingu samskipta á rökréttan hátt.

Tilbúnar einingar eru of flóknar vegna þess að við þurfum aðeins nokkrar aðgerðir.

Sem sagt, vandamálið við dagsetninguna er að innbyggðu aðgerðirnar í Apache leyfa ekki að búa til dagsetningu úr framtíðinni og það er engin stærðfræðileg samlagning/frádráttur í innbyggðu föllunum þegar athugað er hvort það sé fyrning.

Það er, þú getur ekki skrifað:

(%{env:zt-cert-date} + 30) > %{DATE}

Aðeins er hægt að bera saman tvær tölur.

Þegar ég leitaði að lausn fyrir Safari vandamálið fann ég áhugaverða grein: Að tryggja HomeAssistant með viðskiptavottorðum (virkar með Safari/iOS)
Það lýsir dæmi um kóða í Lua fyrir Nginx, og sem, eins og það kom í ljós, endurtekur mjög rökfræði þess hluta stillingarinnar sem við höfum þegar innleitt, að undanskildum notkun hmac söltunaraðferðarinnar fyrir hashing ( þetta fannst ekki í Apache).

Það varð ljóst að Lua er tungumál með skýra rökfræði og það er hægt að gera eitthvað einfalt fyrir Apache:

Eftir að hafa rannsakað muninn á Nginx og Apache:

Og tiltækar aðgerðir frá Lua tungumálaframleiðandanum:
22.1 – Dagsetning og tími

Við fundum leið til að stilla env breytur í lítilli Lua skrá til að stilla dagsetningu úr framtíðinni til að bera saman við núverandi.

Svona lítur einfalt Lua handrit út:

require 'apache2'

function handler(r)
    local fmt = '%Y%m%d%H%M%S'
    local timeout = 3600 -- 1 hour

    r.notes['zt-cert-timeout'] = timeout
    r.notes['zt-cert-date-next'] = os.date(fmt,os.time()+timeout)
    r.notes['zt-cert-date-halfnext'] = os.date(fmt,os.time()+ (timeout/2))
    r.notes['zt-cert-date-now'] = os.date(fmt,os.time())

    return apache2.OK
end

Og svona virkar þetta allt saman, með hagræðingu á fjölda vafraköku og skipti um tákn þegar helmingur tímans kemur áður en gamla kökan (táknið) rennur út:

SSLVerifyClient optional

#LuaScope thread
#generate event variables zt-cert-date-next
LuaHookAccessChecker /usr/local/etc/apache24/sslincludes/websocket_token.lua handler early

#запрещаем без сертификата что-то ещё, кроме webscoket
RewriteEngine on
RewriteCond %{SSL:SSL_CLIENT_VERIFY} !=SUCCESS
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule     .? - [F]
#ErrorDocument 403 "You need a client side certificate issued by CAcert to access this site"

#websocket for safari without certauth
<If "%{SSL:SSL_CLIENT_VERIFY} != 'SUCCESS'">
<If "%{HTTP:Upgrade} = 'websocket'">
    SetEnvIf Cookie "zt-cert=([^,;]+),([^,;]+),[^,;]+,([^,;]+)" zt-cert-sha1=$1 zt-cert-date=$2 zt-cert-uid=$3

    <RequireAll>
        Require expr %{sha1:salt1%{env:zt-cert-date}salt3%{env:zt-cert-uid}salt2} == %{env:zt-cert-sha1}
        Require expr %{env:zt-cert-sha1} =~ /^.{40}$/
        Require expr %{env:zt-cert-date} -ge %{env:zt-cert-date-now}
    </RequireAll>
   
    #замещаем авторизацию по владельцу сертификата на авторизацию по номеру протокола
    SSLUserName SSl_PROTOCOL
    SSLOptions -FakeBasicAuth
</If>
</If>

<If "%{SSL:SSL_CLIENT_VERIFY} = 'SUCCESS'">
<If "%{HTTP:Upgrade} != 'websocket'">
    SetEnvIf Cookie "zt-cert=([^,;]+),[^,;]+,([^,;]+)" HAVE_zt-cert-sha1=$1 HAVE_zt-cert-date-halfnow=$2
    SetEnvIfExpr "env('HAVE_zt-cert-date-halfnow') -ge %{TIME} && env('HAVE_zt-cert-sha1')=~/.{40}/" HAVE_zt-cert-sha1-found=1

    Define zt-cert "path=/;Max-Age=%{env:zt-cert-timeout};HttpOnly;Secure;SameSite=Strict"
    Define dates_user "%{env:zt-cert-date-next},%{env:zt-cert-date-halfnext},%{SSL_CLIENT_S_DN_CN}"
    Header set Set-Cookie "expr=zt-cert=%{sha1:salt1%{env:zt-cert-date-next}sal3%{SSL_CLIENT_S_DN_CN}salt2},${dates_user};${zt-cert}" env=!HAVE_zt-cert-sha1-found
</If>
</If>

SetEnvIfExpr "env('HAVE_zt-cert-date-halfnow') -ge %{TIME} && env('HAVE_zt-cert-sha1')=~/.{40}/" HAVE_zt-cert-sha1-found=1
работает,

а так работать не будет
SetEnvIfExpr "env('HAVE_zt-cert-date-halfnow') -ge  env('zt-cert-date-now') && env('HAVE_zt-cert-sha1')=~/.{40}/" HAVE_zt-cert-sha1-found=1 

Vegna þess að LuaHookAccessChecker verður aðeins virkjaður eftir aðgangsskoðanir byggðar á þessum upplýsingum frá Nginx.

Hvernig við hjá ZeroTech tengdum Apple Safari og viðskiptavinavottorð við nettengi

Tengill á heimild mynd.

Eitt í viðbót.

Almennt skiptir ekki máli í hvaða röð leiðbeiningarnar eru skrifaðar í Apache (líklega líka Nginx) stillingum, þar sem á endanum verður allt raðað eftir röð beiðninnar frá notandanum, sem samsvarar kerfi fyrir vinnslu Lua handrit.

Frágangur:

Sýnilegt ástand eftir innleiðingu (markmið):
stjórnun þjónustu og innviða er fáanleg úr farsíma á IOS án viðbótarforrita (VPN), sameinuð og örugg.

Markmiðinu hefur verið náð, vefinnstungur virka og hafa ekki síður öryggisstig en vottorð.

Hvernig við hjá ZeroTech tengdum Apple Safari og viðskiptavinavottorð við nettengi

Heimild: www.habr.com

Bæta við athugasemd