Бид ZeroTech дээр Apple Safari болон үйлчлүүлэгчийн гэрчилгээг вэб залгууртай хэрхэн холбосон

Нийтлэл нь дараахь хүмүүст хэрэгтэй болно.

  • Client Cert гэж юу болохыг мэддэг бөгөөд яагаад мобайл Safari дээр вэб залгуур хэрэгтэйг ойлгодог;
  • Би вэб үйлчилгээг хязгаарлагдмал хүрээний хүмүүст эсвэл зөвхөн өөртөө нийтлэхийг хүсч байна;
  • бүх зүйлийг аль хэдийн хэн нэгэн хийсэн гэж бодож, дэлхийг арай тохь тухтай, аюулгүй болгохыг хүсч байна.

Вэбсокетуудын түүх 8 жилийн өмнөөс эхэлсэн. Өмнө нь аргуудыг урт http хүсэлт (үнэндээ хариулт) хэлбэрээр ашигладаг байсан: хэрэглэгчийн хөтөч сервер рүү хүсэлт илгээж, ямар нэгэн зүйлд хариу өгөхийг хүлээж байсан бөгөөд хариу ирсний дараа дахин холбогдож, хүлээж байв. Гэвч дараа нь вэб залгуурууд гарч ирэв.

Бид ZeroTech дээр Apple Safari болон үйлчлүүлэгчийн гэрчилгээг вэб залгууртай хэрхэн холбосон

Хэдэн жилийн өмнө бид https хүсэлтийг ашиглах боломжгүй цэвэр PHP дээр өөрийн хэрэгжилтийг боловсруулсан, учир нь энэ нь холбоосын давхарга юм. Тун удалгүй бараг бүх вэб серверүүд HTTPS-ээр дамжуулан прокси хүсэлт илгээж, холболтыг сайжруулж сурсан.

Ийм зүйл тохиолдоход вэбсокетууд нь SPA програмуудын бараг анхдагч үйлчилгээ болсон, учир нь серверийн санаачилгаар хэрэглэгчдэд контент өгөх нь хэр тохиромжтой вэ (өөр хэрэглэгчээс мессеж дамжуулах эсвэл зураг, баримт бичиг, үзүүлэнгийн шинэ хувилбарыг татаж авах). өөр хэн нэгэн одоо засварлаж байна).

Хэдийгээр Client Certificate нь бий болоод багагүй хугацаа өнгөрч байгаа ч түүнийг тойрч гарах гэж оролдох үед маш их асуудал үүсгэдэг тул дэмжлэг муутай хэвээр байна. Тэгээд (магадгүй :slightly_smiling_face: ) ийм учраас IOS хөтчүүд (Safari-аас бусад нь) үүнийг ашиглахыг хүсэхгүй байгаа бөгөөд үүнийг дотоод гэрчилгээний дэлгүүрээс хүсэх болно. Сертификатууд нь нэвтрэх/дэвсэх эсвэл ssh түлхүүрүүд эсвэл шаардлагатай портуудыг галт ханаар хаахтай харьцуулахад олон давуу талтай. Гэхдээ энэ нь юуны тухай биш юм.

IOS дээр гэрчилгээ суулгах журам нь маш энгийн (тодорхой зүйлгүй) боловч ерөнхийдөө үүнийг зааврын дагуу хийдэг бөгөөд эдгээр нь Интернетэд маш их байдаг бөгөөд зөвхөн Safari хөтөч дээр ашиглах боломжтой байдаг. Харамсалтай нь Safari нь Client Сert-ийг вэб залгуурт хэрхэн ашиглахаа мэдэхгүй байгаа ч интернетэд ийм гэрчилгээг хэрхэн үүсгэх талаар олон заавар байдаг ч бодит байдал дээр энэ нь боломжгүй юм.

Бид ZeroTech дээр Apple Safari болон үйлчлүүлэгчийн гэрчилгээг вэб залгууртай хэрхэн холбосон

Вэбсокетуудыг ойлгохын тулд бид дараах төлөвлөгөөг ашигласан. асуудал / таамаглал / шийдэл.

Асуудал: IOS болон сертификатын дэмжлэгийг идэвхжүүлсэн бусад программуудад зориулсан Safari гар утасны хөтөч дээрх үйлчлүүлэгчийн сертификатаар хамгаалагдсан нөөцөд хүсэлт илгээх үед вэб залгууруудад дэмжлэг байхгүй.

Таамаглал:

  1. Дотоод/гадаад прокси нөөцийн вэбсокетуудад гэрчилгээ ашиглахын тулд ийм үл хамаарах зүйлийг тохируулах боломжтой.
  2. Вэбсокетуудын хувьд та ердийн (вэбсокет биш) хөтчийн хүсэлтийн үед үүссэн түр зуурын сессүүдийг ашиглан өвөрмөц, аюулгүй, хамгаалалттай холболт үүсгэж болно.
  3. Түр зуурын сессийг нэг прокси вэб сервер (зөвхөн суурилуулсан модулиуд болон функцууд) ашиглан хийж болно.
  4. Түр зуурын сессийн токенуудыг бэлэн Apache модулиар аль хэдийн хэрэгжүүлсэн.
  5. Түр зуурын сессийн токенуудыг харилцан үйлчлэлийн бүтцийг логикоор төлөвлөх замаар хэрэгжүүлж болно.

Хэрэгжүүлсний дараа харагдах байдал.

Зорилго: Үйлчилгээ, дэд бүтцийн менежментийг гар утаснаасаа нэмэлт програмгүйгээр (VPN гэх мэт) IOS дээр ашиглах боломжтой, нэгдсэн, аюулгүй байх ёстой.

Нэмэлт зорилго: цаг хугацаа, нөөцийг хэмнэнэ/утасны урсгалыг (вэб залгуургүй зарим үйлчилгээ нь шаардлагагүй хүсэлтийг бий болгодог) хөдөлгөөнт интернетэд агуулгыг хурдан хүргэх.

Хэрхэн шалгах вэ?

1. Хуудсуудыг нээх:

— например, 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. Эсвэл хөгжүүлэгчийн консол дээр:

Бид ZeroTech дээр Apple Safari болон үйлчлүүлэгчийн гэрчилгээг вэб залгууртай хэрхэн холбосон

Таамаглалыг шалгах:

1. Дотоод/гадаад прокси нөөцийн вэб залгуурт гэрчилгээг (байхгүй гэдгийг мэдэж байгаа) ашиглахын тулд ийм үл хамаарах зүйлийг тохируулах боломжтой.

Эндээс 2 шийдлийг олсон:

a) түвшинд

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

хандалтын түвшинг өөрчлөх.

Энэ арга нь дараахь нюансуудтай.

  • Сертификатын баталгаажуулалт нь итгэмжлэгдсэн эх сурвалжид хүсэлт гаргасны дараа, өөрөөр хэлбэл хүсэлтийн шуудангаар гар барьсны дараа хийгддэг. Энэ нь прокси эхлээд ачаалагдах ба дараа нь хамгаалагдсан үйлчилгээнд хандах хүсэлтийг тасална гэсэн үг юм. Энэ нь муу, гэхдээ чухал биш;
  • http2 протоколд. Энэ нь ноорог хэвээр байгаа бөгөөд хөтөч үйлдвэрлэгчид үүнийг хэрхэн хэрэгжүүлэхээ мэдэхгүй байна. RFC 8740 "TLS 1.3-г HTTP/2-тэй ашиглах"-ыг хэрэгжүүлэх;
  • Энэ боловсруулалтыг хэрхэн нэгтгэх нь тодорхойгүй байна.

b) Үндсэн түвшинд ssl-г гэрчилгээгүйгээр зөвшөөрнө.

SSLVerifyClient нь => SSLVerifyClient-г нэмэлтээр шаарддаг боловч ийм холболтыг гэрчилгээгүйгээр боловсруулах тул энэ нь прокси серверийн аюулгүй байдлын түвшинг бууруулдаг. Гэсэн хэдий ч, та дараах зааврын дагуу прокси үйлчилгээнд хандахаас татгалзаж болно:

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-ийн тухай нийтлэлээс олж болно: Apache серверийн үйлчлүүлэгчийн гэрчилгээний баталгаажуулалт

Хоёр сонголтыг хоёуланг нь туршсан бөгөөд "b" хувилбарыг олон талт байдал, http2 протоколтой нийцтэй байдлаар сонгосон.

Энэхүү таамаглалыг баталгаажуулахын тулд тохиргооны талаар олон туршилт хийсэн бөгөөд дараахь загваруудыг туршиж үзсэн болно.

хэрэв = шаардах = дахин бичих

Үр дүн нь дараах үндсэн загвар юм.

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>

Сертификат эзэмшигчийн одоо байгаа зөвшөөрлийг харгалзан, гэхдээ гэрчилгээ байхгүй байгаа тул би байхгүй гэрчилгээ эзэмшигчийг SSl_PROTOCOL (SSL_CLIENT_S_DN_CN-ийн оронд) хувьсагчийн аль нэг хэлбэрээр нэмэх шаардлагатай болсон, баримт бичигт дэлгэрэнгүй мэдээлэл:

Apache модуль mod_ssl

Бид ZeroTech дээр Apple Safari болон үйлчлүүлэгчийн гэрчилгээг вэб залгууртай хэрхэн холбосон

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>

Туршилтаар энэ нь ажиллаж байгааг харуулсан. Хэрэглэгчийн хөтөчөөр дамжуулан Cookie-г өөртөө шилжүүлэх боломжтой.

3. Түр зуурын сессүүдийг нэг прокси вэб сервер (зөвхөн суулгагдсан модулиуд болон функцууд) ашиглан хийж болно.

Өмнө нь олж мэдсэнээр Apache нь нөхцөлт бүтцийг бий болгох боломжийг олгодог маш олон үндсэн функцтэй байдаг. Гэсэн хэдий ч, бид хэрэглэгчийн вэб хөтөч дээр байгаа мэдээллээ хамгаалах хэрэгсэл хэрэгтэй байгаа тул юуг, яагаад хадгалах, ямар суулгасан функцийг ашиглахаа тогтооно.

  • Бидэнд амархан тайлах боломжгүй жетон хэрэгтэй.
  • Бидэнд хуучирсан шинж тэмдэг, сервер дээр хуучирсан эсэхийг шалгах чадвартай жетон хэрэгтэй.
  • Бидэнд гэрчилгээ эзэмшигчтэй холбогдох жетон хэрэгтэй.

Энэ нь токеныг хөгшрүүлэхийн тулд хэш функц, давс, огноог шаарддаг. Баримт бичигт үндэслэн Apache HTTP сервер дэх илэрхийлэл Бид бүгдээрээ sha1 болон %{TIME}-д бэлэн байна.

Үүний үр дүнд ийм загвар гарч ирэв:

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

Зорилгодоо хүрсэн боловч серверийн хуучирсан (та жилийн настай күүки ашиглаж болно) асуудалтай байгаа бөгөөд энэ нь жетон хэдийгээр дотоод хэрэглээнд аюулгүй боловч үйлдвэрлэлийн (масс) ашиглахад аюултай гэсэн үг юм.

Бид ZeroTech дээр Apple Safari болон үйлчлүүлэгчийн гэрчилгээг вэб залгууртай хэрхэн холбосон

4. Түр зуурын сессийн токенуудыг бэлэн Apache модулиар аль хэдийн хэрэгжүүлсэн.

Өмнөх давталтаас нэг чухал асуудал үлдсэн - жетон хөгшрөлтийг хянах боломжгүй байсан.

Бид үүнийг хийх боломжтой бэлэн модулийг хайж байна: apache token json two factor auth

Тийм ээ, бэлэн модулиуд байдаг, гэхдээ тэдгээр нь бүгд тодорхой үйлдлүүдтэй холбоотой бөгөөд сесс болон нэмэлт күүки эхлүүлэх хэлбэрээр олдвортой байдаг. Энэ нь хэсэг хугацаанд биш юм.
Бид таван цаг хайсан ч тодорхой үр дүнд хүрээгүй.

5. Түр зуурын сессийн токенуудыг харилцан үйлчлэлийн бүтцийг логикоор төлөвлөх замаар хэрэгжүүлж болно.

Бэлэн модулиуд нь хэтэрхий төвөгтэй, учир нь бидэнд хэдхэн функц хэрэгтэй болно.

Огноотой холбоотой асуудал нь Apache-ийн суулгасан функцууд нь ирээдүйд огноо үүсгэхийг зөвшөөрдөггүй бөгөөд хуучирсан эсэхийг шалгах үед суулгагдсан функцуудад математикийн нэмэх/хасах үйлдэл байхгүй байгаа явдал юм.

Өөрөөр хэлбэл, та бичих боломжгүй:

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

Та зөвхөн хоёр тоог харьцуулж болно.

Safari-тай холбоотой асуудлыг шийдэх арга замыг хайж байхдаа би сонирхолтой нийтлэл олов: HomeAssistant-ийг үйлчлүүлэгчийн гэрчилгээгээр хамгаалах (Safari/iOS дээр ажилладаг)
Энэ нь Nginx-д зориулсан Луа дахь кодын жишээг тайлбарласан бөгөөд хэш хийхэд hmac давслах аргыг эс тооцвол бидний аль хэдийн хэрэгжүүлсэн тохиргооны хэсгийн логикийг маш их давтдаг. Энэ нь Apache-д олдсонгүй).

Луа бол тодорхой логиктой хэл бөгөөд Апачигийн хувьд энгийн зүйл хийх боломжтой болох нь тодорхой болсон.

Nginx болон Apache хоёрын ялгааг судалсны дараа:

Луа хэлний үйлдвэрлэгчээс авах боломжтой функцууд:
22.1 - Огноо, цаг

Бид ирээдүйн огноог одоогийнхтой харьцуулахын тулд жижиг Lua файлд env хувьсагчдыг тохируулах аргыг олсон.

Энгийн Луа скрипт иймэрхүү харагдаж байна:

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

Хуучин күүки (жетон) дуусахаас өмнөх хагас цаг болоход күүкиний тоог оновчтой болгож, токеныг солих зэргээр бүх зүйл бүхэлдээ ингэж ажилладаг.

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 

Учир нь LuaHookAccessChecker нь зөвхөн Nginx-ийн энэ мэдээлэлд үндэслэн хандалтыг шалгасны дараа идэвхжих болно.

Бид ZeroTech дээр Apple Safari болон үйлчлүүлэгчийн гэрчилгээг вэб залгууртай хэрхэн холбосон

Эх сурвалж руу холбох зураг.

Дахиад нэг юм.

Ерөнхийдөө Apache (магадгүй Nginx) тохиргоонд зааврыг ямар дарааллаар бичсэн байх нь хамаагүй, учир нь эцэст нь бүх зүйлийг боловсруулах схемд тохирсон хэрэглэгчийн хүсэлтийн дарааллаар ангилах болно. Луа скриптүүд.

Дуусгах:

Хэрэгжүүлсний дараа харагдах байдал (зорилго):
Үйлчилгээ, дэд бүтцийн менежментийг гар утаснаасаа нэмэлт програм (VPN)гүйгээр IOS дээр ашиглах боломжтой, нэгдсэн бөгөөд аюулгүй.

Зорилгодоо хүрч, вэбсокетууд ажиллаж, гэрчилгээнээс багагүй аюулгүй байдлын түвшинтэй болсон.

Бид ZeroTech дээр Apple Safari болон үйлчлүүлэгчийн гэрчилгээг вэб залгууртай хэрхэн холбосон

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх