Ki jan nou nan ZeroTech konekte Apple Safari ak sètifika kliyan ak websockets

Atik la pral itil pou moun ki:

  • konnen kisa Client Cert e li konprann poukisa li bezwen websockets sou mobil Safari;
  • Mwen ta renmen pibliye sèvis entènèt pou yon sèk limite moun oswa pou mwen sèlman;
  • panse ke tout bagay te deja fè pa yon moun, epi li ta renmen fè mond lan yon ti kras pi pratik ak pi an sekirite.

Istwa websockets te kòmanse anviwon 8 ane de sa. Précédemment, metòd yo te itilize nan fòm demann http long (aktyèlman repons): navigatè itilizatè a voye yon demann nan sèvè a epi tann pou li reponn yon bagay, apre repons lan li konekte ankò epi tann. Men, Lè sa a, websockets parèt.

Ki jan nou nan ZeroTech konekte Apple Safari ak sètifika kliyan ak websockets

Kèk ane de sa, nou devlope pwòp aplikasyon nou an nan PHP pi, ki pa ka itilize demann https, paske sa a se kouch lyen an. Sa pa gen lontan, prèske tout serveurs entènèt te aprann fè demann proxy sou https ak sipò koneksyon: ajou.

Lè sa a te rive, websockets te vin prèske sèvis default pou aplikasyon SPA, paske li se pratik pou bay itilizatè a kontni sou inisyativ sèvè a (transmèt yon mesaj soti nan yon lòt itilizatè oswa telechaje yon nouvo vèsyon imaj, dokiman, prezantasyon). ke yon lòt moun ap modifye kounye a).

Malgre ke Sètifika Kliyan te alantou pou kèk tan, li toujou rete mal sipòte, paske li kreye anpil pwoblèm lè w ap eseye kontoune li. Epi (pètèt :slightly_smiling_face: ) se poutèt sa navigatè IOS (tout eksepte Safari) pa vle sèvi ak li epi mande li nan magazen sètifika lokal la. Sètifika gen anpil avantaj konpare ak kle konekte/pase oswa ssh oswa fèmen pò ki nesesè yo atravè yon firewall. Men, se pa sa sa a se sou.

Sou iOS, pwosedi a pou enstale yon sètifika se byen senp (pa san spesifik), men an jeneral li se fè dapre enstriksyon yo, nan ki gen anpil sou entènèt la ak ki disponib sèlman pou navigatè a Safari. Malerezman, Safari pa konnen ki jan yo sèvi ak Kliyan Сert pou sipò entènèt, men gen anpil enstriksyon sou entènèt la sou kòman yo kreye tankou yon sètifika, men nan pratik sa a se irealizabl.

Ki jan nou nan ZeroTech konekte Apple Safari ak sètifika kliyan ak websockets

Pou konprann websockets, nou itilize plan sa a: pwoblèm/ipotèz/solisyon.

Pwoblèm: pa gen okenn sipò pou sipò entènèt lè proxy demann nan resous ki pwoteje pa yon sètifika kliyan sou navigatè a mobil Safari pou IOS ak lòt aplikasyon ki te pèmèt sipò sètifika.

Ipotèz:

  1. Li posib pou konfigirasyon yon eksepsyon konsa pou sèvi ak sètifika (konnen ke pa pral genyen okenn) nan websockets nan resous entèn / ekstèn proxy.
  2. Pou websockets, ou ka fè yon koneksyon inik, an sekirite ak defann lè l sèvi avèk sesyon tanporè ki pwodui pandan yon demann navigatè nòmal (ki pa websocket).
  3. Sesyon tanporè yo ka aplike lè l sèvi avèk yon sèl sèvè entènèt prokurasyon (modil ak fonksyon entegre sèlman).
  4. Siy sesyon tanporè yo te deja aplike kòm modil Apache pare yo.
  5. Siy sesyon tanporè yo ka aplike pa lojikman konsepsyon estrikti nan entèraksyon.

Eta vizib apre aplikasyon an.

Objektif travay la: jesyon sèvis ak enfrastrikti ta dwe aksesib nan yon telefòn mobil sou IOS san pwogram adisyonèl (tankou VPN), inifye ak an sekirite.

Objektif adisyonèl: ekonomize tan ak resous/trafik telefòn (kèk sèvis san yo pa sit entènèt jenere demann pa nesesè) ak livrezon pi rapid nan kontni sou Entènèt mobil lan.

Ki jan yo tcheke?

1. Ouvèti paj:

— например, 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. Oswa nan konsole pwomotè a:

Ki jan nou nan ZeroTech konekte Apple Safari ak sètifika kliyan ak websockets

Tès ipotèz:

1. Li posib pou konfigirasyon yon eksepsyon konsa pou sèvi ak sètifika (konnen ke pa pral genyen okenn) nan sipò entènèt nan resous entèn / ekstèn proxy.

2 solisyon yo te jwenn isit la:

a) Nan nivo

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

chanje nivo aksè.

Metòd sa a gen nuans sa yo:

  • Verifikasyon sètifika fèt apre yon demann nan resous proxy a, se sa ki, apre demann lanmen. Sa vle di ke proxy a pral premye chaje ak Lè sa a, koupe demann lan nan sèvis la pwoteje. Sa a se move, men se pa kritik;
  • Nan pwotokòl la http2. Li toujou nan bouyon, ak manifaktirè navigatè yo pa konnen ki jan yo aplike li # info sou tls1.3 http2 post lanmen (pa travay kounye a) Aplike RFC 8740 "Itilize TLS 1.3 ak HTTP/2";
  • Li pa klè ki jan yo inifye pwosesis sa a.

b) Nan yon nivo debaz, pèmèt ssl san yon sètifika.

SSLVerifyClient mande => SSLVerifyClient si ou vle, men sa diminye nivo sekirite sèvè proxy a, paske yo pral trete yon koneksyon konsa san yon sètifika. Sepandan, ou ka plis refize aksè nan sèvis proxy ak direktiv sa a:

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"

Ou ka jwenn plis enfòmasyon detaye nan atik sou ssl: Apache Sèvè Kliyan Sètifika Otantifikasyon

Tou de opsyon yo te teste, opsyon "b" te chwazi pou adaptabilite li yo ak konpatibilite ak pwotokòl http2 la.

Pou konplete verifikasyon ipotèz sa a, li te pran anpil eksperyans ak konfigirasyon an; yo te teste desen sa yo:

si = mande = reekri

Rezilta a se konsepsyon debaz sa a:

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>

Lè w ap konsidere otorizasyon ki deja egziste pa pwopriyetè sètifika a, men ak yon sètifika ki manke, mwen te oblije ajoute yon mèt sètifika ki pa egziste nan fòm youn nan varyab ki disponib SSl_PROTOCOL (olye pou SSL_CLIENT_S_DN_CN), plis detay nan dokiman an:

Apache Modil mod_ssl

Ki jan nou nan ZeroTech konekte Apple Safari ak sètifika kliyan ak websockets

2. Pou websockets, ou ka fè yon koneksyon inik, an sekirite ak pwoteje lè l sèvi avèk sesyon tanporè ki pwodui pandan yon demann navigatè nòmal (ki pa websocket).

Dapre eksperyans anvan, ou bezwen ajoute yon seksyon adisyonèl nan konfigirasyon an nan lòd yo prepare marqueur tanporè pou koneksyon priz entènèt pandan yon demann regilye (ki pa priz entènèt).

#подготовка передача себе С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>

Tès te montre ke li travay. Li posib transfere bonbon nan tèt ou atravè navigatè itilizatè a.

3. Sesyon tanporè yo ka aplike lè l sèvi avèk yon sèl sèvè entènèt prokurasyon (sèlman modil ak fonksyon entegre).

Kòm nou te dekouvri pi bonè, Apache gen yon anpil nan fonksyonalite debaz ki pèmèt ou kreye konstriksyon kondisyonèl. Sepandan, nou bezwen mwayen pou pwoteje enfòmasyon nou yo pandan ke li nan navigatè itilizatè a, kidonk nou etabli kisa pou estoke ak poukisa, ak ki fonksyon entegre nou pral itilize:

  • Nou bezwen yon siy ki pa ka fasil dekode.
  • Nou bezwen yon siy ki gen obsolesans bati nan li ak kapasite nan tcheke obsolesans sou sèvè a.
  • Nou bezwen yon siy ki pral asosye ak pwopriyetè sètifika a.

Sa a mande pou yon fonksyon hachage, yon sèl, ak yon dat pou laj jeton an. Ki baze sou dokiman an Ekspresyon nan Apache HTTP sèvè nou gen tout bagay ki soti nan bwat sha1 ak %{TIME}.

Rezilta a te konsepsyon sa a:

#нет сертификата, и обращение к 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>

Objektif la te reyalize, men gen pwoblèm ak obsolesans sèvè (ou ka itilize yon bonbon ane), ki vle di ke marqueur yo, byenke san danje pou itilizasyon entèn yo, yo pa an sekirite pou itilizasyon endistriyèl (mas).

Ki jan nou nan ZeroTech konekte Apple Safari ak sètifika kliyan ak websockets

4. Siy sesyon tanporè yo te deja aplike kòm modil Apache pare yo.

Yon pwoblèm enpòtan te rete nan iterasyon anvan an - enkapasite a kontwole aje siy.

Nou ap chèche yon modil pare ki fè sa, dapre mo sa yo: apache token json two factor auth

Wi, gen modil pare, men yo tout mare nan aksyon espesifik epi yo gen zafè nan fòm lan nan kòmanse yon sesyon ak bonbon adisyonèl. Sa vle di, pa pou yon ti tan.
Li te pran nou senk èdtan rechèch, ki pa t 'bay yon rezilta konkrè.

5. siy sesyon tanporè yo ka aplike pa lojikman konsepsyon estrikti nan entèraksyon.

Modil ki pare yo twò konplèks, paske nou sèlman bezwen yon koup nan fonksyon.

Sa yo te di, pwoblèm nan ak dat la se ke Apache a bati-an fonksyon pa pèmèt jenere yon dat nan tan kap vini an, epi pa gen okenn adisyon / soustraksyon matematik nan fonksyon yo bati-an lè tcheke pou obsolesans.

Sa vle di, ou pa ka ekri:

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

Ou ka sèlman konpare de nimewo.

Pandan m ap chèche yon solisyon pou pwoblèm Safari a, mwen te jwenn yon atik enteresan: Sekirize HomeAssistant ak sètifika kliyan (travay ak Safari/iOS)
Li dekri yon egzanp nan kòd nan Lua pou Nginx, epi ki, jan li te tounen soti, anpil repete lojik nan pati sa a nan konfigirasyon an ke nou te deja aplike, ak eksepsyon nan itilize nan metòd la Hmac sale pou hachage ( sa a pa te jwenn nan Apache).

Li te vin klè ke Lua se yon lang ki gen lojik klè, epi li posib fè yon bagay senp pou Apache:

Èske w gen etidye diferans lan ak Nginx ak Apache:

Ak fonksyon ki disponib nan manifakti lang Lua:
22.1 - Dat ak Lè

Nou te jwenn yon fason yo mete varyab env nan yon ti dosye Lua yo nan lòd yo mete yon dat soti nan tan kap vini an konpare ak yon sèl aktyèl la.

Men sa yon senp script Lua sanble:

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

Men ki jan li tout travay an total, ak optimize kantite bonbon ak ranplasman siy la lè mwatye tan an rive anvan ansyen bonbon (jeton) ekspire:

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 

Paske LuaHookAccessChecker pral sèlman aktive apre chèk aksè ki baze sou enfòmasyon sa a ki soti nan Nginx.

Ki jan nou nan ZeroTech konekte Apple Safari ak sètifika kliyan ak websockets

Link nan sous imaj.

Yon lòt bagay ankò.

An jeneral, li pa enpòtan nan ki lòd direktiv yo ekri nan konfigirasyon Apache (pwobableman tou Nginx), depi nan fen a tout bagay pral klase ki baze sou lòd la nan demann lan soti nan itilizatè a, ki koresponn ak konplo a pou pwosesis. Lua scripts.

Konplete:

Eta vizib apre aplikasyon (objektif):
jesyon sèvis ak enfrastrikti disponib nan yon telefòn mobil sou IOS san pwogram adisyonèl (VPN), inifye ak an sekirite.

Objektif la te reyalize, sipò entènèt travay epi yo gen yon nivo sekirite pa mwens pase yon sètifika.

Ki jan nou nan ZeroTech konekte Apple Safari ak sètifika kliyan ak websockets

Sous: www.habr.com

Add nouvo kòmantè