TR EN DE AZ
GitHub Repository mhrgl.com
Ana Səhifə / Arxitektura / Sistem Dizaynı

🏗️ Sistem Arxitekturası & Mühəndislik Əsaslandırması

AiPBX korporativ şəbəkələrdəki sərt təhlükəsizlik divarı maneələrini, WebRTC media ötürmə çətinliklərini, çoxlu cihaz qarışıqlığını və yüksək eyni vaxtlı ani mesajlaşma ehtiyaclarını həll etmək üçün xüsusi olaraq layihələndirilib.

1. Vahid Qatlı Arxitektura (Layered Topology)

AiPBX modul və zəif bağlı (loosely coupled) çoxqatlı struktur üzərində qurulub. Müştərilərdən gələn bütün trafik bir nöqtədə qarşılanır və protokol səviyyəsində alt xidmətlərə yönləndirilir:

ASCII Arxitektura Topologiyası
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                                      CLIENT LAYER                                       │
│   ┌───────────────────────────────┐               ┌─────────────────────────────────┐   │
│   │     Android Mobile App        │               │      Web Browser Client         │   │
│   │     (Kotlin + WebRTC/SIP)     │               │   (WebRTC Softphone + Portal)   │   │
│   └───────────────┬───────────────┘               └────────────────┬────────────────┘   │
└───────────────────┼────────────────────────────────────────────────┼────────────────────┘
                    │ HTTPS / WSS / TURNS (Single Port: 443)         │ HTTPS / WSS / TURNS
                    ▼                                                ▼
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                   EDGE INGRESS: NGINX PORT 443 ALPN MULTIPLEXER (L4)                    │
│   Nginx stream (ssl_preread on, PROXY protocol) — routes by ALPN, never decrypts:       │
│                                                                                         │
│   ├── [ ALPN Present ] (http/1.1, h2: Web Browsers, Mobile REST API, Management)        │
│   │     └──► Streamed to Apache 2.4 TLS Termination (127.0.0.1:8443)                    │
│   │                                                                                     │
│   └── [ ALPN Empty / None ] (WebRTC TURNS media relay behind restrictive firewalls)     │
│         └──► Streamed to coturn TURNS (via relay 127.0.0.1:15349 ──► 5349)             │
└───────────────────────────────────┬────────────────────────────────┬────────────────────┘
                                    │                                │
                     [ ALPN Present ]                                [ No ALPN ]
                                    ▼                                │
┌───────────────────────────────────────────────────────┐            │
│          APPLICATION & WEBSOCKET PROXY TIER           │            ▼
│  Apache 2.4 (127.0.0.1:8443 with TLS Termination)     │ ┌─────────────────────────────┐
│   ├── /                 ──► PHP 8 MVC Web Portal      │ │        COTURN RELAY         │
│   ├── /ws               ──► Asterisk WebRTC (8088/ws) │ │  TURNS Server (Port 5349)  │
│   └── /chat/ws          ──► Go Chat Engine (8086/ws)  │ │  Zero Media Loss for        │
│                                                       │ │  Symmetric NAT Traversal    │
│  Port 80: HTTP Redirect & Let's Encrypt ACME HTTP-01  │ └─────────────────────────────┘
└──────────┬────────────────────────┬───────────────────┘
           │                        │
           ▼                        ▼
┌─────────────────────┐  ┌─────────────────────┐
│      PHP 8 MVC      │  │     Asterisk 22     │
│     Web Portal      │  │     VoIP Engine     │
│  (Hardened Runtime) │  │    (PJSIP/WebRTC)   │
└──────────┬──────────┘  └──────────┬──────────┘
           │                        │
           │     AMI (Port 5038)    │
           ├────────────────────────┘
           │
           ▼
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                                       DATA LAYER                                        │
│  MariaDB 11 (utf8mb4_unicode_ci) — Two-Tier Privilege Security Model:                   │
│   ├── aipbx_portal   (Runtime DML: SELECT, INSERT, UPDATE, DELETE only)                 │
│   └── aipbx_migrator (Schema DDL: Phinx Migrations only)                                │
└─────────────────────────────────────────────────────────────────────────────────────────┘

2. Niyə Port 443 ALPN Stream Multipleksləşdirmə?

Klassik santral quraşdırması çölə çoxlu port açır: SIP üçün 5060, WebRTC WSS üçün 8089, STUN/TURN üçün 3478 və 5349. Otel, xəstəxana, universitet, qonaq Wi-Fi şəbəkələri və korporativ şəbəkələrin çoxu isə çölə yalnız 80 və 443-ə icazə verir. Belə şəbəkədə brauzer portala daxil olur, amma telefon qoşulmur, ya da zəng qurulur, amma səs gəlmir.

💡
AiPBX həlli: 443-ü nginx-in stream (L4) modulu dinləyir və TLS-i açmadan ClientHello içindəki ALPN sahəsinə baxır. ALPN olan bağlantılar (brauzer, mobil API, WSS) Apache-yə, ALPN-siz TLS bağlantıları (WebRTC-nin TURNS müştərisi) coturn-a gedir. Portal, /ws SIP-over-WebSocket, /chat söhbət və TURNS media relesi tək port və tək sertifikatla işləyir.

Quraşdırmanın yazdığı konfiqurasiya

/etc/nginx/aipbx-stream.conf
stream {
    map $ssl_preread_alpn_protocols $aipbx_backend {
        default     127.0.0.1:8443;    # ALPN present: Apache (portal, /ws, /chat)
        ""          127.0.0.1:15349;   # no ALPN: TURNS, via the relay below
        ~stun\.turn 127.0.0.1:15349;   # RFC 7443 TURN clients
    }

    server {
        listen 443;
        listen [::]:443;
        ssl_preread on;                # read the ClientHello, never decrypt
        proxy_pass $aipbx_backend;
        proxy_protocol on;             # pass the real client address
        proxy_timeout 3600s;           # long calls and idle WebSockets survive
        proxy_connect_timeout 5s;
    }

    # coturn cannot read the PROXY header: this hop strips it.
    server {
        listen 127.0.0.1:15349 proxy_protocol;
        proxy_pass 127.0.0.1:5349;
        proxy_timeout 3600s;
    }
}

nginx TLS-i açmadığı üçün müştərinin real IP ünvanını Apache-yə PROXY protokolu başlığı ilə ötürür (RemoteIPProxyProtocol On). Bu olmasaydı, hər sorğu 127.0.0.1-dən gəlirmiş kimi görünərdi; giriş cəhdlərinin məhdudlaşdırılması hamını bir nəfər sayar, fail2ban hücumçunu deyil, özünü bloklayar, audit qeydləri isə yararsız olardı. Apache HTTPS üçün yalnız 127.0.0.1:8443-ü dinləyir, yəni ona çöldən birbaşa çatmaq mümkün deyil.

3. Real Dünyada NAT, STUN/TURN və WebRTC

VoIP-də "səs gəlmir", "bir tərəf eşidir" və "zəng gec başlayır" şikayətlərinin demək olar ki, hamısı NAT və təhlükəsizlik divarından qaynaqlanır. Aşağıdakı ssenarilərin hər biri sahədə rastlaşdığımız bir problemdir. Hər kartda əvvəl istifadəçinin gördüyü əlamət, sonra səbəbi, ən sonda isə AiPBX-in bunu necə həll etdiyi göstərilir.

Otel, xəstəxana və ya qonaq Wi-Fi-ı: yalnız 443 açıqdır

Əlamət
Portal açılır, softphone qeydiyyatdan keçir, amma zəng səssiz qalır və ya bir neçə saniyədən sonra kəsilir.
Səbəb
Səs (RTP) UDP tələb edir; şəbəkə UDP-ni və 3478/5349-u bağlayıb. Media üçün yeganə çıxış yolu 443/TCP-dir.
AiPBX nə edir
Müştəriyə turns:domen-adı:443?transport=tcp verilir. nginx ALPN-siz TLS-i coturn-a ötürür; səs TLS daxilində, adi HTTPS kimi görünərək axır. coturn releyi serverin öz ünvanında açır (relay-ip); 443-dən gələn bağlantı 127.0.0.1-dən göründüyü üçün bu olmadan rele loopback-da açılır və səs getmirdi. /etc/ai-pbx.env faylında TURNS_PORT=443 ilə aktivləşdirilir (quraşdırma standartı 5349).

Korporativ təhlükəsizlik divarı STUN/TURN-u imzasından tanıyır

Əlamət
Port açıq görünsə də, adi STUN/TURN işləmir; ICE namizəd toplama uzanır, zəng gec başlayır.
Səbəb
DPI edən cihazlar şifrəsiz STUN/TURN paketlərini məzmunundan tanıyıb atır. Bunu xarici şəbəkədən test edərək təsdiqlədik.
AiPBX nə edir
Müştərilərə yalnız TURNS (TLS) ünvanı verilir; adi STUN/TURN namizədləri və xarici STUN serverləri əlavə edilmir. İşləməyən namizədlər çıxarıldığı üçün ICE gözləmədən nəticəyə çatır. Android tətbiqi ümumi STUN serverindən yalnız TURN təyin edilmədikdə istifadə edir.

Server buludda, özəl IP arxasında (1:1 NAT)

Əlamət
Xaricdəki telefonlar qeydiyyatdan keçir, amma səs birtərəflidir və ya ümumiyyətlə yoxdur.
Səbəb
Asterisk SDP-yə öz özəl IP-sini (məs. 10.x) yazır; qarşı tərəf səsi əlçatmaz olan bu ünvana göndərir.
AiPBX nə edir
Portalda daxil edilən xarici IP hər transporta external_media_address / external_signaling_address kimi, WebRTC üçün isə rtp.conf faylında ayrıca [ice_host_candidates] bölməsinə özəl IP => xarici IP kimi yazılır; include_local_address sayəsində LAN-dakı müştərilər özəl ünvandan istifadə etməyə davam edir.

Zənglər vebdə 4–5 san, mobildə 30 san gec başlayır

Əlamət
Zəng düyməsi basıldıqdan sonra qarşı tərəf bir neçə saniyə gec çalır.
Səbəb
rtp.conf faylındakı stunaddr açıq olduqda Asterisk hər RTP sessiyasında STUN sorğusu göndərir; ICE soketinə cavab heç vaxt çatmadığı üçün 3 cəhd × 3 san gözləyirdi. Loglarda ölçdük: hər WebRTC zəngi ~6 san bloklanırdı.
AiPBX nə edir
stunaddr standart olaraq bağlıdır. Xarici ünvan artıq statik ice_host_candidates uyğunlaşdırması ilə məlumdur, hər zəng üçün şəbəkə sorğusu edilmir. Lazım olarsa rtp_stunaddr_enabled sistem ayarı ilə yenidən açıla bilər.

Evdən işləyən, modem arxasındakı masa telefonu

Əlamət
Qarşı tərəf eşidilir, amma telefonun səsi getmir; telefon bir müddət sonra "qeydiyyatsız" görünür.
Səbəb
Telefon SIP mesajlarına özəl IP-sini yazır; modemin NAT qeydi boş qaldıqda bağlanır.
AiPBX nə edir
Endpoint-lər force_rport, rewrite_contact və rtp_symmetric ilə yaradılır: cavab və səs paketin həqiqətən gəldiyi ünvan/porta göndərilir. direct_media=no ilə səs həmişə PBX üzərindən axır; iki NAT arxasındakı telefonun bir-birini tapmasına ehtiyac qalmır. qualify mütəmadi yoxlama ilə NAT qeydini açıq saxlayır.

Çağrı mərkəzi tabı saatlarla açıqdır

Əlamət
Səhər problemsiz işləyən veb telefon günortadan sonra zəngləri səssiz qoşur; Asterisk kanalı RTP vaxt aşımı ilə bağlayır.
Səbəb
TURN kimliyi 1 saat etibarlı idi və səhifə yüklənərkən bir dəfə alınırdı. Müddəti bitdikdə coturn 401 Unauthorized verib releyi qurmurdu; ölçmədə kimliklərin etibarlılığı 17–40 dəqiqə əvvəl bitmişdi.
AiPBX nə edir
Kimlik hər 30 dəqiqədən bir arxa planda yenilənir və zəng zamanı əlavə gecikmə olmur. Kimliklər coturn-un paylaşılan sirri ilə HMAC-SHA1 kimi istifadəçiyə xas və müddətli yaradılır; statik TURN parolu nə kodda, nə də JavaScript-də olur.

Telefon Wi-Fi-dan 4G-yə keçir

Əlamət
Şəbəkə dəyişəndə gələn zənglər artıq telefona çatmır; PBX köhnə, ölü ünvana zəng edir.
Səbəb
Yeni şəbəkədə telefonun xarici IP-si və portu dəyişir; köhnə qeyd serverdə bir müddət daha "etibarlı" qalır.
AiPBX nə edir
Mobil endpoint-in AOR-u təknəfərlikdir (max_contacts=1, remove_existing=yes): yeni qeydiyyat gələn kimi köhnəsi silinir. Tətbiq hər 5 dəqiqədən bir yenidən qeydiyyatdan keçərək operator NAT-ını təzə saxlayır; tətbiq yuxudadırsa, zəngdən əvvəl push bildirişi ilə oyadılır.

Eyni daxili nömrə həm masada, həm brauzerdə

Əlamət
Brauzer gələn zəngi "Called with SDP without DTLS fingerprint" xətası ilə rədd edir.
Səbəb
Masa telefonu adi RTP, WebRTC isə DTLS-SRTP + ICE + AVPF tələb edir. Tək endpoint ilə onlardan biri mütləq yanlış təklif alır.
AiPBX nə edir
Hər daxili nömrə üçün iki ayrı endpoint və iki ayrı AOR yaradılır (1000 və 1000-webrtc); çarpaz bağlama edilmir. Paralel çalma dialplan-da iki kontakt siyahısını birləşdirməklə edilir, beləliklə hər cihaz öz media profili ilə çağırılır.

90 gündə bir sertifikat yenilənməsi

Əlamət
Portal yeni sertifikatla işləyir, amma TURNS səssizcə pozulur; xaricdəki istifadəçilərin səsi kəsilir.
Səbəb
coturn turnserver istifadəçisi ilə işləyir və root-a məxsus açarı oxuya bilmir; buna görə sertifikatın bir surətindən istifadə edir və həmin surət yenilənmir.
AiPBX nə edir
Tək aktiv sertifikat portala, TURNS-a və SIP-TLS-ə tətbiq olunur. Yeniləmə qarmağı sertifikatı tam zənciri ilə coturn və Asterisk-ə kopyalayır və xidmətləri yenidən yükləyir. Təhlükəsizlik → Sertifikatlar səhifəsi özü-imzalı, yanlış ada aid və ya zənciri natamam sertifikatı TURNS-u pozmazdan əvvəl göstərir.

Hansı port nə üçün açıqdır?

Port Kim istifadə edir Bağlıdırsa
443/tcp Portal, mobil API, WebRTC siqnalı (/ws), söhbət; TURNS_PORT=443 ilə TURNS media relesi də Məcburi
80/tcp Let's Encrypt doğrulaması və HTTPS-ə yönləndirmə Sertifikat yenilənmir
5060/udp+tcp, 5061/tcp Masaüstü telefonlar və SIP trunk-lar (SIP / SIP-TLS) Yalnız WebRTC/mobil istifadə olunursa lazım deyil
10000-20000/udp Asterisk RTP səsi Masaüstü telefon və trunk zəngləri səssiz qalır
3478, 5349 udp+tcp STUN/TURN və TURNS (birbaşa) TURNS_PORT=443 ilə 443 üzərindən davam edir
49152-65535/udp coturn rele portları TURN relesi qurula bilmir
8089/tcp Asterisk-in birbaşa WSS portu, yalnız loopback-da Qəsdən bağlıdır. WSS yalnız 443 üzərindən təqdim olunur

4. Dual-Endpoint PJSIP və WebRTC Arxitekturası

Bazardakı bir çox hazır PBX paketi (FreePBX, Issabel və s.) bir daxili nömrə üçün eyni anda həm aparat masaüstü telefonu, həm də WebRTC brauzerini qoşmaqda çətinlik çəkir. NAT arxasındakı masaüstü telefonun və WebRTC-nin şifrələmə və media ötürmə tələbləri tamamilə əksdir:

  • WebRTC (Brauzer & Mobil): WSS nəqliyyatı, DTLS-SRTP şifrələməsi, ICE namizədləri, AVPF profili və Opus səs kodeki tələb edir.
  • Masaüstü Telefon (IP Telefon / ATA): UDP və ya TLS nəqliyyatı, SDES-SRTP və ya şifrəsiz RTP, SAVP/RTP profili və G.711u/a kodeki istifadə edir.
Endpoint ID İstifadə Məqsədi Nəqliyyat & Port Şifrələmə & Kodek
1000 Aparat IP Telefon / Masaüstü SIP UDP / TLS (Port 5060/5061) SDES-SRTP / G.711a, G.722, G.729
1000-webrtc Veb Brauzer & Native Mobil Müştəri WSS (443 → Apache /ws → Asterisk :8088) DTLS-SRTP + ICE / Opus (HD Audio)
📞
Paralel Zəng (Forked Ringing): 1000 daxili nömrəsinə zəng edildikdə Asterisk dialplanı Dial(PJSIP/1000&PJSIP/1000-webrtc,30) əmri ilə masadakı aparat telefonu və cibdəki mobil tətbiqi eyni anda zəng çaldırır. İlk cavab verən zəngi qəbul edir, digəri səssizcə bağlanır.

5. Müstəqil Go Real-Time WebSocket Xidməti

PHP qısa ömürlü HTTP sorğu-cavab dövrləri üçün mükəmməldir, lakin minlərlə açıq WebSocket bağlantısını idarə etmək üçün optimallaşdırılmayıb. AiPBX santral daxili ani mesajlaşma və çoxiştirakçılı qrup söhbəti mühərrikini təmiz Go (Golang) ilə hazırlayıb (/opt/aipbx/bin/aipbx-chat):

  • Mikro Yaddaş İstehlakı: 10.000 aktiv eyni vaxtlı WebSocket bağlantısı cəmi ~28 MB RAM istifadə edir.
  • Goroutine Kanalları: Hər bağlantı üçün ağır sistem axını yerinə yüngül Go kanalları istifadə olunur.
  • Sıfır Xarici Asılılıq: Tək statik binar fayl kimi kompilyasiya olunur, əlavə kitabxana tələb etmir.
  • Mövcudluq (Presence) & Yazır Bildirişi: Onlayn/oflayn statusu və yazır məlumatı millisaniyələr ərzində yayılır.

6. Asterisk Konfiqurasiya Sinxronizasiya Dövrü

AiPBX-də Asterisk konfiqurasiya faylları heç vaxt əllə redaktə edilmir. Verilənlər bazası (MariaDB) sistemin yeganə həqiqət mənbəyidir (Single Source of Truth). Bir ayar dəyişdirildikdə aşağıdakı atomar dövr icra olunur:

Konfiqurasiya & Avtomatik Geri Qaytarma Axını
Web UI / REST API Request
        │
        ▼
Controller Validation & Auth Check
        │
        ▼
Service writes to MariaDB (DML)
        │
        ▼
Sync Generator (src/sync/*.php)
        ├── 1. Backs up existing file to .bak
        ├── 2. Queries DB and generates modular files under /etc/asterisk/pbx/*.conf
        └── 3. Issues Asterisk reload command (dialplan reload, queue reload...)
                │
                ├── [ SUCCESS ] ──► Updates audit log, removes .bak cleanly.
                └── [ FAILURE ] ──► AUTOMATIC ROLLBACK: Restores .bak immediately,
                                    prevents downtime, and logs error report.

7. İkipilləli MariaDB Təhlükəsizlik Modeli

İstifadəçi Adı İstifadə Sahəsi SQL Səlahiyyətləri Məhdudlaşdırılan Səlahiyyətlər
aipbx_portal PHP Veb Panel & REST API SELECT, INSERT, UPDATE, DELETE DROP, ALTER, CREATE, GRANT (Forbidden)
aipbx_migrator Phinx Verilənlər Bazası Miqrasiyaları (CLI) CREATE, ALTER, INDEX, DROP Local CLI only during schema migrations
Bu Səhifədə