Thina kwaZeroTech sixhume kanjani i-Apple Safari nezitifiketi zeklayenti ngama-websockets

I-athikili izoba usizo kulabo:

  • знает, что такое Client Cert, и понимает для чего ему websocket-ы на мобильном Safari;
  • Ngingathanda ukushicilela izinsiza zewebhu kubantu abambalwa noma kimina kuphela;
  • ucabanga ukuthi yonke into isivele yenziwe othile, futhi angathanda ukwenza umhlaba ube lula futhi uphephe.

Umlando wama-websockets waqala cishe eminyakeni eyi-8 edlule. Ngaphambilini, izindlela zazisetshenziswa ngendlela yezicelo ezinde ze-http (empeleni izimpendulo): isiphequluli somsebenzisi sithumele isicelo kuseva futhi silinde ukuthi siphendule okuthile, ngemva kwempendulo sixhume futhi salinda. Kodwa-ke kwavela ama-websockets.

Thina kwaZeroTech sixhume kanjani i-Apple Safari nezitifiketi zeklayenti ngama-websockets

Eminyakeni embalwa edlule, sakha ukuqaliswa kwethu ku-PHP ehlanzekile, engakwazi ukusebenzisa izicelo ze-https, njengoba lesi isendlalelo sesixhumanisi. Esikhathini esingeside esidlule, cishe wonke amaseva ewebhu afunde ukwenza izicelo zommeleli phezu kwe-https kanye nokuxhumeka kosekelo:thuthukisa.

Lapho lokhu kwenzeka, ama-websockets aba cishe isevisi ezenzakalelayo yezinhlelo zokusebenza ze-SPA, ngoba kulula kangakanani ukuhlinzeka ngokuqukethwe kumsebenzisi ngokusuka kweseva (dlulisa umlayezo ovela komunye umsebenzisi noma landa inguqulo entsha yesithombe, idokhumenti, isethulo. ukuthi omunye umuntu uyahlela okwamanje) .

Yize Isitifiketi Seklayenti sesinesikhathi eside sikhona, sisalokhu sisekelwa kabi, njengoba sidala izinkinga eziningi lapho sizama ukusidlula. Futhi (okungenzeka :slightly_smiling_face: ) yingakho iziphequluli ze-IOS (zonke ngaphandle kwe-Safari) zingafuni ukuyisebenzisa futhi ziyicele esitolo sezitifiketi sendawo. Izitifiketi zinezinzuzo eziningi uma kuqhathaniswa nokhiye wokungena/wokudlula noma we-ssh noma ukuvala izimbobo ezidingekayo ngodonga lokuvikela. Kodwa akukhona lokho okumayelana nalokhu.

На IOS процедура установки сертификата довольно проста (не без специфики), но в общем делается по инструкциям, которых в сети очень много и которые доступны только для браузера Safari. К сожалению, Safari не умеет использовать Сlient Сert для веб-сокетов, но в интернете есть множество инструкций, как сделать такой сертификат, но на практике это недостижимо.

Thina kwaZeroTech sixhume kanjani i-Apple Safari nezitifiketi zeklayenti ngama-websockets

Ukuze siqonde ama-websockets, sisebenzise uhlelo olulandelayo: inkinga/inkoleloze/isixazululo.

Inkinga: akukho usekelo lwamasokhethi ewebhu uma ufaka izicelo zommeleli ezinsizeni ezivikelwe yisitifiketi seklayenti kusiphequluli seselula seSafari se-IOS nezinye izinhlelo zokusebenza ezinike amandla ukusekelwa kwesitifiketi.

Ama-hypotheses:

  1. Kungenzeka ukulungisa lokho okuhlukile ukuze usebenzise izitifiketi (ukwazi ukuthi ngeke zibe khona) kuma-websockets wezinsiza zangaphakathi/zangaphandle ze-proxied.
  2. Kuma-websockets, ungenza ukuxhumana okuyingqayizivele, okuvikelekile futhi okuvikelekayo usebenzisa izikhathi zesikhashana ezikhiqizwa ngesikhathi sesicelo sesiphequluli esijwayelekile (okungesona esewebhu).
  3. Amaseshini esikhashana angenziwa kusetshenziswa iseva yewebhu yommeleli oyedwa (amamojula akhelwe ngaphakathi nemisebenzi kuphela).
  4. Amathokheni esikhathi sesikhashana asevele asetshenziswa njengamamojula e-Apache enziwe ngomumo.
  5. Amathokheni eseshini yesikhashana angasetshenziswa ngokuklama ngokunengqondo isakhiwo sokusebenzisana.

Isimo esibonakalayo ngemva kokuqaliswa.

Umgomo womsebenzi: Ukuphathwa kwezinsizakalo nengqalasizinda kufanele kufinyeleleke kumakhalekhukhwini ku-IOS ngaphandle kwezinhlelo ezengeziwe (njenge-VPN), ezihlanganisiwe futhi zivikelekile.

Umgomo ongeziwe: ukonga isikhathi nezinsiza/ithrafikhi yocingo (amanye amasevisi ngaphandle kwamasokhethi ewebhu enza izicelo ezingadingekile) ngokulethwa okusheshayo kokuqukethwe ku-inthanethi yeselula.

Ungahlola kanjani?

1. Ukuvula amakhasi:

— например, 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. Noma kukhonsoli yonjiniyela:

Thina kwaZeroTech sixhume kanjani i-Apple Safari nezitifiketi zeklayenti ngama-websockets

Ukuhlolwa kwe-hypothesis:

1. Kuyenzeka ulungiselele okuhlukile ukuze usebenzise izitifiketi (uwazi ukuthi ngeke zibe khona) kumasokhethi ewebhu wezinsiza ezisebenza ngommeleli zangaphakathi/zangaphandle.

Тут было найдено 2 решения:

a) Ezingeni

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

shintsha izinga lokufinyelela.

Le ndlela inama-nuances alandelayo:

  • Ukuqinisekiswa kwesitifiketi kwenzeka ngemva kwesicelo esisetshenziswa esisetshenziswa njenge-proxied, okungukuthi, ukuxhawula isicelo sokuthunyelwe. Lokhu kusho ukuthi ummeleli uzoqala alayishe bese enqamula isicelo kusevisi evikelwe. Lokhu kubi, kodwa akukona ukugxeka;
  • Kuphrothokholi ye-http2. Isalungiswa, futhi abakhiqizi beziphequluli abazi ukuthi bayisebenzise kanjani #info about tls1.3 http2 post handshake (ayisebenzi manje) Implement RFC 8740 «Using TLS 1.3 with HTTP/2»;
  • Akucaci ukuthi kuhlanganisa kanjani lokhu kucubungula.

b) Ezingeni eliyisisekelo, vumela i-ssl ngaphandle kwesitifiketi.

SSLVerifyClient require => SSLVerifyClient optional, но это снижает уровень защиты proxy-сервера, так как такое соединение будет обработано без сертификата. Однако можно далее запретить доступ к проксируемым сервисам такой директивой:

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"

Более подробная информация – в статье о ssl: Ukuqinisekiswa Kwesitifiketi Seklayenti Leseva ye-Apache

Оба варианта были проверены, выбран вариант «б» за универсальность и совместимость с протоколом http2.

Ukuqedela ukuqinisekiswa kwalo mbono, kuthathe izivivinyo eziningi ngokucushwa; le miklamo elandelayo yahlolwa:

if = zidinga = bhala kabusha

Получилась следующая базовая конструкция:

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>

Ngokucabangela ukugunyazwa okukhona komnikazi wesitifiketi, kodwa ngesitifiketi esishodayo, kwadingeka ngengeze umnikazi wesitifiketi owayengekho ngendlela yokuhlukahluka okutholakalayo SSl_PROTOCOL (esikhundleni se-SSL_CLIENT_S_DN_CN), imininingwane eyengeziwe kumadokhumenti:

Apache Module mod_ssl

Thina kwaZeroTech sixhume kanjani i-Apple Safari nezitifiketi zeklayenti ngama-websockets

2. Для веб-сокетов можно сделать уникальное безопасное и защищаемое соединение с помощью временных сессий, которые генерируются при обычном (не веб-сокет) запросе браузера.

Исходя из предыдущего опыта нужно добавить дополнительную секцию в конфигурацию, чтобы при обычном (не веб-сокет) запросе готовить временные токены для веб-сокет соединений.

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

Ukuhlola kubonise ukuthi kuyasebenza. Kuyenzeka ukuthi udlulisele amakhukhi kuwe ngesiphequluli somsebenzisi.

3. Amaseshini esikhashana angenziwa kusetshenziswa iseva yewebhu yommeleli oyedwa (amamojula akhelwe ngaphakathi kuphela nemisebenzi).

Как мы выяснили ранее, у Apache довольно много core-функциональности, которая позволяет создавать условные конструкции. Однако нам нужны средства защиты нашей информации, пока она находится в пользовательском браузере, поэтому устанавливаем, что и для чего хранить, и какие встроенные функции будем задействовать:

  • Sidinga ithokheni engakwazi ukuqoshwa kalula.
  • Sidinga ithokheni elinokuphelelwa yisikhathi okwakhelwe kulo kanye nekhono lokuhlola ukuphelelwa yisikhathi kuseva.
  • Нужен такой токен, который будет связан с владельцем сертификата.

Lokhu kudinga umsebenzi we-hashing, usawoti, kanye nedethi yokuguga ithokheni. Ngokusekelwe kumadokhumenti Expressions in Apache HTTP Server sinakho konke ngaphandle kwebhokisi elithi sha1 kanye ne-%{TIME}.

Umphumela waba lo mklamo:

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

Цель достигнута, но есть проблемы с серверным устареванием (можно использовать Cookie годичной давности), а значит токены, хоть и безопасны для внутреннего использования, но небезопасны для промышленного (массового).

Thina kwaZeroTech sixhume kanjani i-Apple Safari nezitifiketi zeklayenti ngama-websockets

4. Amathokheni esikhathi sesikhashana asevele asetshenziswa njengamamojula e-Apache enziwe ngomumo.

С предыдущей итерации осталась одна существенная проблема — невозможность контролировать устаревание токена.

Sifuna imojula eyenziwe ngomumo eyenza lokhu, ngokusho kwamagama: apache token json two factor auth

Yebo, kukhona amamojula enziwe ngomumo, kodwa wonke ahlanganiswe ezenzweni ezithile futhi anezinto zobuciko ngendlela yokuqala iseshini namakhukhi engeziwe. Okungukuthi, hhayi okwesikhashana.
Kwasithatha amahora amahlanu ukucinga, okungazange kunikeze umphumela obambekayo.

5. Amathokheni eseshini yesikhashana angasetshenziswa ngokuklama ngokunengqondo isakhiwo sokusebenzisana.

Amamojula enziwe ngomumo ayinkimbinkimbi kakhulu, ngoba sidinga imisebenzi embalwa kuphela.

Uma sekushiwo, inkinga ngedethi ukuthi imisebenzi eyakhelwe ngaphakathi ye-Apache ayikuvumeli ukukhiqiza idethi kusukela esikhathini esizayo, futhi akukho okungeziwe/ukukhipha kwezibalo emisebenzini eyakhelwe ngaphakathi uma ibheka ukuphelelwa yisikhathi.

Okusho ukuthi, awukwazi ukubhala:

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

Ungakwazi ukuqhathanisa izinombolo ezimbili kuphela.

При поиске обхода проблемы Safari нашлась интересная статья: Ukuvikela i-HomeAssistant ngezitifiketi zeklayenti (isebenza ne-Safari/iOS)
Ichaza isibonelo sekhodi ku-Lua ye-Nginx, futhi okuthi, njengoba kwenzeka, iphinda kakhulu ingqondo yaleyo ngxenye yokucushwa esesivele siyisebenzise, ​​ngaphandle kokusetshenziswa kwendlela ye-hmac salting ye-hashing ( lokhu akutholakalanga ku-Apache).

Kwaba sobala ukuthi isiLua siwulimi olunengqondo ecacile, futhi kungenzeka ukwenza okuthile okulula ku-Apache:

Изучив разницу с Nginx и Apache:

Futhi imisebenzi etholakalayo evela kumkhiqizi wolimi lwesiLua:
22.1 - Usuku kanye nesikhathi

Sithole indlela yokusetha okuguquguqukayo kwe-env efayeleni elincane le-Lua ukuze sibeke idethi yesikhathi esizayo ukuze siqhathanise neyamanje.

Nansi indlela umbhalo we-Lua olula obukeka ngayo:

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

И вот так это всё работает в сумме, c оптимизацией числа Cookie и заменой токена при наступлении половинного времени до истечения старых Cookie (токена):

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 

Ngoba i-LuaHookAccessChecker izosebenza kuphela ngemva kokuhlolwa kokufinyelela okusekelwe kulolu lwazi oluvela ku-Nginx.

Thina kwaZeroTech sixhume kanjani i-Apple Safari nezitifiketi zeklayenti ngama-websockets

Xhuma emthonjeni izithombe.

Ещё один момент.

Ngokuvamile, akunandaba ukuthi iziqondiso zibhalwe kanjani ekucushweni kwe-Apache (mhlawumbe futhi i-Nginx), ngoba ekugcineni yonke into izohlungwa ngokusekelwe kuhlelo lwesicelo esivela kumsebenzisi, oluhambisana nohlelo lokucubungula. Lua scripts.

Ukuqedwa:

Isimo esibonakalayo ngemva kokuqaliswa (umgomo):
Ukuphathwa kwezinsizakalo nengqalasizinda kuyatholakala kumakhalekhukhwini ku-IOS ngaphandle kwezinhlelo ezengeziwe (VPN), ezihlangene futhi zivikelekile.

Цель достигнута, веб-сокеты работают и обладают не меньшим уровнем безопасности, чем сертификат.

Thina kwaZeroTech sixhume kanjani i-Apple Safari nezitifiketi zeklayenti ngama-websockets

Source: www.habr.com

Engeza amazwana