Carane kita ing ZeroTech nyambung Apple Safari lan sertifikat klien karo websockets

Artikel kasebut bakal migunani kanggo wong sing:

  • ngerti apa iku Sertifikasi Klien lan ngerti sebabe butuh soket web ing Safari seluler;
  • Aku pengin nerbitake layanan web menyang bunderan winates utawa mung kanggo aku;
  • mikir sing kabeh wis rampung dening wong, lan kaya kanggo nggawe donya sethitik luwih trep lan luwih aman.

Sejarah websockets diwiwiti udakara 8 taun kepungkur. Sadurunge, cara kayata panjalukan http sing dawa (bener-bener tanggapan) digunakake: browser pangguna ngirim panjaluk menyang server lan ngenteni supaya bisa mangsuli, sawise tanggapan kasebut disambungake maneh lan ngenteni. Nanging banjur websockets katon.

Carane kita ing ZeroTech nyambung Apple Safari lan sertifikat klien karo websockets

Sawetara taun kepungkur, kita ngembangake implementasine dhewe ing PHP murni, sing ora bisa nggunakake panjalukan https, amarga iki minangka lapisan link. Ora suwe, meh kabeh server web sinau kanggo njaluk proxy liwat https lan ndhukung sambungan: nganyarke.

Nalika kedadeyan kasebut, websockets meh dadi layanan standar kanggo aplikasi SPA, amarga trep kanggo nyedhiyakake konten menyang pangguna kanthi inisiatif server (ngirim pesen saka pangguna liya utawa ngundhuh versi anyar saka gambar, dokumen, presentasi. yen wong liya lagi nyunting).

Sanajan Sertifikat Klien wis ana sawetara wektu, nanging isih kurang didhukung, amarga nggawe akeh masalah nalika nyoba ngliwati. Lan (bisa uga: slightly_smiling_face: ) pramila browser IOS (kabeh kajaba Safari) ora pengin nggunakake lan njaluk saka toko sertifikat lokal. Sertifikat duwe akeh kaluwihan dibandhingake karo login / pass utawa tombol ssh utawa nutup port sing dibutuhake liwat firewall. Nanging dudu bab iki.

Ing iOS, prosedur nginstal sertifikat cukup prasaja (ora tanpa spesifik), nanging umume ditindakake miturut instruksi, sing ana akeh ing Internet lan mung kasedhiya kanggo browser Safari. Sayange, Safari ora ngerti cara nggunakake Client Π‘ert kanggo soket web, nanging ana akeh instruksi ing Internet babagan carane nggawe sertifikat kasebut, nanging ing praktik iki ora bisa ditindakake.

Carane kita ing ZeroTech nyambung Apple Safari lan sertifikat klien karo websockets

Kanggo mangerteni websockets, kita nggunakake rencana ing ngisor iki: masalah / hipotesis / solusi.

Masalah: ora ana dhukungan kanggo soket web nalika njaluk proxy menyang sumber daya sing dilindhungi sertifikat klien ing browser seluler Safari kanggo IOS lan aplikasi liyane sing wis ngaktifake dhukungan sertifikat.

Hipotesis:

  1. Sampeyan bisa ngonfigurasi pangecualian kasebut kanggo nggunakake sertifikat (ngerti ora ana) menyang soket web sumber daya internal / eksternal.
  2. Kanggo websockets, sampeyan bisa nggawe sambungan sing unik, aman lan bisa dipertahankan nggunakake sesi sauntara sing digawe sajrone panjalukan browser normal (non-websocket).
  3. Sesi sementara bisa dileksanakake nggunakake siji server web proxy (modul lan fungsi sing dibangun mung).
  4. Token sesi sementara wis dileksanakake minangka modul Apache sing wis siap.
  5. Token sesi sementara bisa dileksanakake kanthi ngrancang struktur interaksi kanthi logis.

Negara katon sawise implementasine.

Tujuan saka karya: manajemen layanan lan infrastruktur kudu bisa diakses saka ponsel ing IOS tanpa program tambahan (kayata VPN), manunggal lan aman.

Tujuan tambahan: ngirit wektu lan sumber daya / lalu lintas telpon (sawetara layanan tanpa soket web ngasilake panjaluk sing ora perlu) kanthi pangiriman konten sing luwih cepet ing Internet seluler.

Cara mriksa?

1. Kaca pambuka:

β€” Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, 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. Utawa ing konsol pangembang:

Carane kita ing ZeroTech nyambung Apple Safari lan sertifikat klien karo websockets

Uji hipotesis:

1. Sampeyan bisa ngatur pangecualian kasebut kanggo nggunakake sertifikat (ngerti ora ana) menyang soket web sumber daya proksi internal / eksternal.

2 solusi ditemokake ing kene:

a) Ing tingkat

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

ngganti tingkat akses.

Cara iki nduweni nuansa ing ngisor iki:

  • Verifikasi sertifikat kedadeyan sawise panjaluk menyang sumber daya sing diproksi, yaiku, jabat tangan panjaluk kirim. Iki tegese proxy bakal mbukak dhisik banjur ngilangi panjaluk menyang layanan sing dilindhungi. Iki ala, nanging ora kritis;
  • Ing protokol http2. Iki isih ana ing konsep, lan produsen browser ora ngerti carane ngetrapake #info babagan tls1.3 http2 kirim jabat tangan (ora bisa digunakake saiki) Ngleksanakake RFC 8740 "Using TLS 1.3 with HTTP/2";
  • Ora jelas carane nggabungake pangolahan iki.

b) Ing tingkat dhasar, ngidini ssl tanpa sertifikat.

SSLVerifyClient mbutuhake => SSLVerifyClient opsional, nanging iki nyuda tingkat keamanan server proxy, amarga sambungan kasebut bakal diproses tanpa sertifikat. Nanging, sampeyan bisa nolak akses menyang layanan proksi kanthi arahan ing ngisor iki:

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"

Informasi sing luwih rinci bisa ditemokake ing artikel babagan ssl: Otentikasi Sertifikat Klien Server Apache

Loro-lorone opsi dites, opsi "b" dipilih kanggo versatility lan kompatibilitas karo protokol http2.

Kanggo ngrampungake verifikasi hipotesis iki, butuh akeh eksperimen karo konfigurasi; desain ing ngisor iki diuji:

yen = mbutuhake = nulis maneh

Asil punika desain dhasar ing ngisor iki:

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>

Nganggep wewenang sing wis ana dening pemilik sertifikat, nanging kanthi sertifikat sing ilang, aku kudu nambah pemilik sertifikat sing ora ana ing wangun salah sawijining variabel SSl_PROTOCOL sing kasedhiya (tinimbang SSL_CLIENT_S_DN_CN), rincian liyane ing dokumentasi:

Modul Apache mod_ssl

Carane kita ing ZeroTech nyambung Apple Safari lan sertifikat klien karo websockets

2. Kanggo websockets, sampeyan bisa nggawe sambungan unik, aman lan dilindhungi nggunakake sesi sauntara sing kui sak normal (non-websocket) panjalukan browser.

Adhedhasar pengalaman sadurunge, sampeyan kudu nambah bagean tambahan kanggo konfigurasi kanggo nyiapake token sementara kanggo sambungan soket web sajrone panjaluk biasa (non-web).

#ΠΏΠΎΠ΄Π³ΠΎΡ‚ΠΎΠ²ΠΊΠ° ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π° сСбС Π‘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>

Tes nuduhake yen bisa. Sampeyan bisa nransfer Cookies menyang dhewe liwat browser pangguna.

3. Sesi sementara bisa dileksanakake nggunakake siji server web proxy (mung modul lan fungsi sing dibangun).

Kaya sing wis dingerteni sadurunge, Apache duwe akeh fungsi inti sing ngidini sampeyan nggawe konstruksi kondisional. Nanging, kita butuh sarana kanggo nglindhungi informasi nalika ana ing browser pangguna, mula kita nemtokake apa sing kudu disimpen lan ngapa, lan fungsi apa sing bakal digunakake:

  • We kudu token sing ora bisa gampang decoded.
  • We kudu token sing wis obsolescence dibangun menyang lan kemampuan kanggo mriksa obsolescence ing server.
  • Kita butuh token sing bakal digandhengake karo pemilik sertifikat kasebut.

Iki mbutuhake fungsi hashing, uyah, lan tanggal kanggo umur token. Adhedhasar dokumentasi Ekspresi ing Apache HTTP Server kita duwe kabeh metu saka kothak sha1 lan %{TIME}.

Hasile desain iki:

#Π½Π΅Ρ‚ сСртификата, ΠΈ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠ΅ ΠΊ 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>

Ing goal wis ngrambah, nanging ana masalah karo obsolescence server (sampeyan bisa nggunakake Cookie taun-lawas), kang tegese token, sanajan aman kanggo nggunakake internal, ora aman kanggo industri (massal) nggunakake.

Carane kita ing ZeroTech nyambung Apple Safari lan sertifikat klien karo websockets

4. Token sesi sementara wis dileksanakake minangka modul Apache sing wis siap.

Siji masalah penting tetep saka pengulangan sadurunge - ora bisa ngontrol penuaan token.

We are looking for a modul siap-digawe sing nindakake iki, miturut tembung: apache token json two factor auth

Ya, ana modul siap-digawe, nanging kabeh padha disambungake menyang tumindak tartamtu lan duwe artefak ing wangun miwiti sesi lan Cookies tambahan. Tegese, ora sedhela.
Butuh limang jam kanggo nggoleki, sing ora menehi asil konkrit.

5. Token sesi sementara bisa dileksanakake kanthi ngrancang struktur interaksi kanthi logis.

Modul siap-digawe rumit banget, amarga kita mung butuh sawetara fungsi.

Menawi mekaten, masalah karo tanggal iku Apache kang dibangun ing fungsi ora ngidini ngasilaken tanggal saka mangsa, lan ora ana tambahan / pangurangan matΓ©matika ing fungsi dibangun ing nalika mriksa obsolescence.

Yaiku, sampeyan ora bisa nulis:

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

Sampeyan mung bisa mbandhingake rong nomer.

Nalika nggoleki solusi kanggo masalah Safari, aku nemokake artikel sing menarik: Ngamanake HomeAssistant nganggo sertifikat klien (bisa nganggo Safari/iOS)
Iki nggambarake conto kode ing Lua kanggo Nginx, lan sing, ternyata, mbaleni logika bagean konfigurasi sing wis ditindakake, kajaba nggunakake metode salting hmac kanggo hashing ( iki ora ditemokake ing Apache).

Dadi jelas yen Lua minangka basa kanthi logika sing jelas, lan bisa ditindakake kanthi gampang kanggo Apache:

Sawise sinau bedane karo Nginx lan Apache:

Lan fungsi sing kasedhiya saka pabrikan basa Lua:
22.1 – Tanggal lan Wektu

Kita nemokake cara kanggo nyetel variabel env ing file Lua cilik supaya bisa nyetel tanggal ing mangsa ngarep kanggo mbandhingake karo sing saiki.

Iki minangka skrip Lua sing prasaja:

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

Lan iki cara kerjane kabeh, kanthi optimalisasi jumlah Cookie lan ngganti token nalika setengah wektu sadurunge Cookie lawas (token) kadaluwarsa:

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 

Amarga LuaHookAccessChecker mung bakal diaktifake sawise mriksa akses adhedhasar informasi iki saka Nginx.

Carane kita ing ZeroTech nyambung Apple Safari lan sertifikat klien karo websockets

Link menyang sumber gambar.

Sedhela maneh.

UmumΓ©, ora preduli ing urutan apa arahan ditulis ing konfigurasi Apache (mbokmenawa uga Nginx), amarga ing pungkasan kabeh bakal diurutake adhedhasar urutan panyuwunan pangguna, sing cocog karo skema pangolahan. skrip Lua.

Rampung:

Katon status sawise implementasine (goal):
manajemen layanan lan infrastruktur kasedhiya saka telpon seluler ing IOS tanpa program tambahan (VPN), manunggal lan aman.

Tujuane wis digayuh, soket web bisa digunakake lan duwe tingkat keamanan ora kurang saka sertifikat.

Carane kita ing ZeroTech nyambung Apple Safari lan sertifikat klien karo websockets

Source: www.habr.com

Add a comment