{"id":495489,"date":"2026-09-21T20:55:33","date_gmt":"2026-09-21T20:55:33","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=495489"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=495489","title":{"rendered":"\u041a\u0430\u043a \u043c\u044b \u043f\u043e\u0434\u0440\u0443\u0436\u0438\u043b\u0438 WebRTC \u0441 Asterisk: \u0434\u0435\u0442\u0435\u043a\u0442\u0438\u0432\u043d\u0430\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u0437\u0432\u043e\u043d\u043a\u0430"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0417\u0430\u0434\u0430\u0447\u0430 \u0437\u0432\u0443\u0447\u0430\u043b\u0430 \u043d\u0435\u0432\u0438\u043d\u043d\u043e: \u0434\u0432\u0430 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430, \u043a\u043d\u043e\u043f\u043a\u0430 \u00abCall\u00bb, \u0433\u043e\u043b\u043e\u0441 \u0432 \u043e\u0431\u0435 \u0441\u0442\u043e\u0440\u043e\u043d\u044b. \u041f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c &#8212; Asterisk \u043d\u0430 VPS, WebRTC \u0432 Chrome, SIP \u043f\u043e\u0432\u0435\u0440\u0445 WebSocket. \u0427\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0439\u0442\u0438 \u043d\u0435 \u0442\u0430\u043a?<\/p>\n<p>\u0412\u0441\u0451. \u041f\u044f\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0445 \u0431\u0430\u0433\u043e\u0432 \u0441 \u043e\u0434\u043d\u0438\u043c \u0438 \u0442\u0435\u043c \u0436\u0435 \u0441\u0438\u043c\u043f\u0442\u043e\u043c\u043e\u043c &#8212; \u00ab\u043d\u0435\u0442 \u0437\u0432\u0443\u043a\u0430\u00bb. \u042d\u0442\u043e \u0434\u0435\u0442\u0435\u043a\u0442\u0438\u0432\u043d\u0430\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u0437\u0432\u043e\u043d\u043a\u0430: \u0432\u0441\u0435 \u0431\u0430\u0433\u0438 \u0440\u0435\u0430\u043b\u044c\u043d\u044b, \u0432\u0441\u0435 \u0433\u0440\u0430\u0431\u043b\u0438 &#8212; \u043d\u0430\u0448\u0438. IP-\u0430\u0434\u0440\u0435\u0441\u0430 \u0438 \u043a\u0440\u0435\u0434\u044b \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u0437\u0430\u043c\u0435\u043d\u0435\u043d\u044b \u043d\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e97\/30d\/2f6\/e9730d2f6dc1ef972eec7d7e41015dbc.jpeg\" alt=\"\u041e\u0445\u043e\u0442\u0430 \u043d\u0430 \u043f\u0440\u043e\u043f\u0430\u0432\u0448\u0438\u0439 \u0437\u0432\u0443\u043a\" width=\"2400\" height=\"1792\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/e97\/30d\/2f6\/e9730d2f6dc1ef972eec7d7e41015dbc.jpeg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e97\/30d\/2f6\/e9730d2f6dc1ef972eec7d7e41015dbc.jpeg 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041e\u0445\u043e\u0442\u0430 \u043d\u0430 \u043f\u0440\u043e\u043f\u0430\u0432\u0448\u0438\u0439 \u0437\u0432\u0443\u043a<\/figcaption><\/div>\n<\/figure>\n<hr\/>\n<h3>\u0413\u043b\u0430\u0432\u0430 1. \u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0437\u0430\u0441\u043b\u0443\u0436\u0438\u043b\u0438<\/h3>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u0441\u0435\u0431\u0435 \u0441\u0445\u0435\u043c\u0443. VPS \u0441 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u043c IP\u00a0<code>203.0.113.10<\/code>. \u041d\u0430 \u043d\u0451\u043c \u043a\u0440\u0443\u0442\u0438\u0442\u0441\u044f Docker-\u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0441\u00a0<strong>Asterisk 22.8<\/strong>\u00a0&#8212; \u043e\u043f\u0435\u043d\u0441\u043e\u0440\u0441\u043d\u043e\u0439 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u043d\u0446\u0438\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0443\u043c\u0435\u0435\u0442 \u0432\u0441\u0451: \u043e\u0442 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0445 SIP-\u0437\u0432\u043e\u043d\u043a\u043e\u0432 \u0434\u043e WebRTC. \u0420\u044f\u0434\u043e\u043c &#8212;\u00a0<strong>Coturn<\/strong>, STUN\/TURN-\u0441\u0435\u0440\u0432\u0435\u0440, \u0442\u043e\u0436\u0435 \u0432 Docker, \u0432 host-\u0440\u0435\u0436\u0438\u043c\u0435.<\/p>\n<p>\u041d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 &#8212; \u0434\u0432\u0430 HTML-\u0444\u0430\u0439\u043b\u0430.\u00a0<code>index.html<\/code>\u00a0&#8212; \u0437\u0432\u043e\u043d\u044f\u0449\u0438\u0439 (\u0430\u0431\u043e\u043d\u0435\u043d\u0442\u00a0<code>3001<\/code>).\u00a0<code>3002.html<\/code>\u00a0&#8212; \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u0439 \u0441 \u0430\u0432\u0442\u043e-\u043e\u0442\u0432\u0435\u0442\u043e\u043c. \u041e\u0431\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u00a0<strong>JsSIP<\/strong>\u00a0&#8212; JavaScript-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 SIP-\u0441\u0442\u0435\u043a \u043f\u0440\u044f\u043c\u043e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435. SIP-\u0441\u0438\u0433\u043d\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438\u0434\u0451\u0442 \u043f\u043e\u00a0<strong>WSS<\/strong>\u00a0(WebSocket Secure) \u0447\u0435\u0440\u0435\u0437 \u043f\u043e\u0440\u0442 8089. \u041c\u0435\u0434\u0438\u0430 &#8212; \u043f\u043e\u00a0<strong>RTP<\/strong>\u00a0(Real-time Transport Protocol), \u0437\u0430\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c\u0443 \u0432\u00a0<strong>DTLS-SRTP<\/strong>, \u0447\u0435\u0440\u0435\u0437 \u043f\u043e\u0440\u0442\u044b 18000\u201318100 UDP.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ce4\/3ab\/787\/ce43ab787a1df6fc104d9723f7f618eb.jpeg\" alt=\"\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430: \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u044b, Asterisk \u0438 Coturn \u043d\u0430 VPS, \u0441\u0438\u0433\u043d\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e WSS, \u043c\u0435\u0434\u0438\u0430 \u043f\u043e RTP\" width=\"2400\" height=\"1792\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/ce4\/3ab\/787\/ce43ab787a1df6fc104d9723f7f618eb.jpeg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ce4\/3ab\/787\/ce43ab787a1df6fc104d9723f7f618eb.jpeg 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430: \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u044b, Asterisk \u0438 Coturn \u043d\u0430 VPS, \u0441\u0438\u0433\u043d\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e WSS, \u043c\u0435\u0434\u0438\u0430 \u043f\u043e RTP<\/figcaption><\/div>\n<\/figure>\n<p>\u041a\u043e\u0434\u0435\u043a &#8212;\u00a0<strong>Opus<\/strong>\u00a0(48 kHz, 2 \u043a\u0430\u043d\u0430\u043b\u0430). \u041d\u0435 MP3, \u043d\u0435 AMR, \u043d\u0435 G.711. Opus &#8212; \u044d\u0442\u043e \u043a\u043e\u0434\u0435\u043a, \u0440\u043e\u0436\u0434\u0451\u043d\u043d\u044b\u0439 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438: \u0430\u0434\u0430\u043f\u0442\u0438\u0432\u043d\u044b\u0439 \u0431\u0438\u0442\u0440\u0435\u0439\u0442, \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u0430\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0446\u0438\u044f \u043e\u0448\u0438\u0431\u043e\u043a (FEC), \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0430 \u043e\u0442 5 \u043c\u0441. \u0412 \u043c\u0438\u0440\u0435 VoIP \u0435\u0441\u0442\u044c \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u043a\u043e\u0434\u0435\u043a\u043e\u0432 &#8212;\u00a0<strong>G.711<\/strong>\u00a0(\u03bc-law\/A-law, \u043e\u043d \u0436\u0435 PCMU\/PCMA) \u0434\u043b\u044f \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u0438 \u0441 PSTN,\u00a0<strong>G.722<\/strong>\u00a0\u0434\u043b\u044f HD-\u0433\u043e\u043b\u043e\u0441\u0430,\u00a0<strong>AMR<\/strong>\u00a0\u0432 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0441\u0435\u0442\u044f\u0445,\u00a0<strong>G.729<\/strong>\u00a0\u0441 \u0435\u0433\u043e \u043f\u043b\u0430\u0442\u043d\u044b\u043c\u0438 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u044f\u043c\u0438. \u041d\u043e \u0434\u043b\u044f WebRTC Opus &#8212; \u043a\u043e\u0440\u043e\u043b\u044c. Chrome \u0434\u0430\u0436\u0435 \u043d\u0435 \u0443\u043c\u0435\u0435\u0442 \u0434\u043e\u0433\u043e\u0432\u0430\u0440\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043e \u0447\u0451\u043c-\u0442\u043e \u0434\u0440\u0443\u0433\u043e\u043c \u043f\u0435\u0440\u0432\u044b\u043c.<\/p>\n<p>Asterisk \u0442\u043e\u0436\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 Opus (\u0447\u0435\u0440\u0435\u0437\u00a0<code>allow=opus<\/code>\u00a0\u0432\u00a0<code>pjsip.conf<\/code>), \u043f\u043b\u044e\u0441 PCMU \u0438 PCMA \u043a\u0430\u043a fallback. \u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0432\u044b\u0431\u043e\u0440\u0430 \u043a\u043e\u0434\u0435\u043a\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432\u043e \u0432\u0440\u0435\u043c\u044f\u00a0<strong>SDP-\u043e\u0431\u043c\u0435\u043d\u0430<\/strong>\u00a0(Session Description Protocol): \u043a\u0430\u0436\u0434\u0430\u044f \u0441\u0442\u043e\u0440\u043e\u043d\u0430 \u0437\u0430\u044f\u0432\u043b\u044f\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u043a\u043e\u0434\u0435\u043a\u043e\u0432 \u0441 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0430\u043c\u0438, \u0438 \u043e\u043d\u0438 \u043d\u0430\u0445\u043e\u0434\u044f\u0442 \u043f\u0435\u0440\u0435\u0441\u0435\u0447\u0435\u043d\u0438\u0435. \u0412\u043e\u0442 \u0442\u0438\u043f\u0438\u0447\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u0438\u0437 SDP:<\/p>\n<pre><code>a=rtpmap:111 opus\/48000\/2a=fmtp:111 minptime=10;useinbandfec=1<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u042d\u0442\u043e Opus \u0441 payload type 111, \u0447\u0430\u0441\u0442\u043e\u0442\u043e\u0439 \u0434\u0438\u0441\u043a\u0440\u0435\u0442\u0438\u0437\u0430\u0446\u0438\u0438 48 \u043a\u0413\u0446, \u0441\u0442\u0435\u0440\u0435\u043e, \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 ptime 10 \u043c\u0441 \u0438 \u0432\u043a\u043b\u044e\u0447\u0451\u043d\u043d\u0430\u044f \u0432\u043d\u0443\u0442\u0440\u0438\u043f\u043e\u043b\u043e\u0441\u043d\u0430\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0446\u0438\u044f \u043e\u0448\u0438\u0431\u043e\u043a.<\/p>\n<p>\u0417\u0432\u0443\u0447\u0438\u0442 \u0441\u0442\u0440\u043e\u0439\u043d\u043e. \u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c Call.<\/p>\n<p>\u0422\u0438\u0448\u0438\u043d\u0430.<\/p>\n<hr\/>\n<h3>\u0413\u043b\u0430\u0432\u0430 2. \u041f\u0435\u0440\u0432\u044b\u0439 \u0437\u0432\u043e\u043d\u043e\u043a: \u00ab180 Ringing\u00bb \u0438 \u043c\u0451\u0440\u0442\u0432\u0430\u044f \u0442\u0438\u0448\u0438\u043d\u0430<\/h3>\n<p>Asterisk \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 INVITE \u043e\u0442\u00a0<code>3001<\/code>, \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u0435\u0433\u043e \u043f\u043e\u00a0<strong>dialplan<\/strong>\u00a0(<code>extensions.conf<\/code>) \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u043e\u0432\u044b\u0439 INVITE \u043a\u00a0<code>3002<\/code>. \u0411\u0440\u0430\u0443\u0437\u0435\u0440\u00a0<code>3002<\/code>\u00a0\u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0437\u0432\u043e\u043d\u043e\u043a, JsSIP \u0441\u0442\u0440\u0435\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u0435\u043c\u00a0<code>newRTCSession<\/code>. \u041d\u0430\u0448 \u043a\u043e\u0434 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u00a0<code>session.answer()<\/code>. Asterisk \u0432\u0438\u0434\u0438\u0442\u00a0<code>180 Ringing<\/code>.<\/p>\n<p>\u041d\u043e\u00a0<code>200 OK<\/code>\u00a0\u043d\u0435 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442.<\/p>\n<p>\u0414\u0432\u0430\u0434\u0446\u0430\u0442\u044c \u0441\u0435\u043a\u0443\u043d\u0434.\u00a0<code>Nobody picked up in 20000 ms<\/code>. Asterisk \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u00a0<code>CANCEL<\/code>, \u0438 \u0437\u0432\u043e\u043d\u043e\u043a \u0443\u043c\u0438\u0440\u0430\u0435\u0442.<\/p>\n<p>\u041f\u0435\u0440\u0432\u0430\u044f \u043c\u044b\u0441\u043b\u044c &#8212;\u00a0<code>getUserMedia()<\/code>. \u042d\u0442\u043e\u0442 \u0432\u044b\u0437\u043e\u0432 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u043c\u0438\u043a\u0440\u043e\u0444\u043e\u043d, \u0438 \u0435\u0441\u043b\u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0434\u0438\u0430\u043b\u043e\u0433 \u00ab\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c?\u00bb &#8212; \u043e\u043d \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442 \u0432\u0441\u0451. \u0420\u0435\u0448\u0435\u043d\u0438\u0435: \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u00a0<code>ensureMic()<\/code>\u00a0<strong>\u0434\u043e<\/strong>\u00a0\u0441\u0442\u0430\u0440\u0442\u0430 JsSIP UA, \u0447\u0442\u043e\u0431\u044b \u043a \u043c\u043e\u043c\u0435\u043d\u0442\u0443 \u0432\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u0437\u0432\u043e\u043d\u043a\u0430 \u043c\u0438\u043a\u0440\u043e\u0444\u043e\u043d \u0443\u0436\u0435 \u0431\u044b\u043b \u0433\u043e\u0442\u043e\u0432.<\/p>\n<p>\u041f\u043e\u043c\u043e\u0433\u043b\u043e? \u041d\u0435\u0442.\u00a0<code>180 Ringing<\/code>\u00a0\u0435\u0441\u0442\u044c,\u00a0<code>200 OK<\/code>\u00a0&#8212; \u043d\u0435\u0442.<\/p>\n<hr\/>\n<h3>\u0413\u043b\u0430\u0432\u0430 3. ICE, \u0438\u043b\u0438 \u041f\u043e\u0447\u0435\u043c\u0443 \u0434\u0432\u0430 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0430 \u043d\u0435 \u043c\u043e\u0433\u0443\u0442 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c<\/h3>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442, \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u044c\u00a0<strong>ICE<\/strong>\u00a0&#8212; Interactive Connectivity Establishment. \u042d\u0442\u043e \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0430\u0431\u0431\u0440\u0435\u0432\u0438\u0430\u0442\u0443\u0440\u0430, \u044d\u0442\u043e \u0446\u0435\u043b\u044b\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0435\u0448\u0430\u0435\u0442 \u0444\u0443\u043d\u0434\u0430\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430: \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 \u0441\u0438\u0434\u044f\u0442 \u0437\u0430 NAT \u0438 \u043d\u0435 \u0437\u043d\u0430\u044e\u0442 \u0441\u0432\u043e\u0435\u0433\u043e \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e\u0433\u043e \u0430\u0434\u0440\u0435\u0441\u0430.<\/p>\n<p>ICE \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u0430\u043a:<\/p>\n<ol>\n<li>\n<p>\u0411\u0440\u0430\u0443\u0437\u0435\u0440 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u00a0<strong>\u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u043e\u0432<\/strong>\u00a0&#8212; \u0430\u0434\u0440\u0435\u0441\u0430, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0434\u043e \u043d\u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0441\u0442\u0443\u0447\u0430\u0442\u044c\u0441\u044f:<\/p>\n<ul>\n<li>\n<p><strong>host<\/strong>\u00a0&#8212; \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0435 IP (192.168.x.x, 10.x.x.x)<\/p>\n<\/li>\n<li>\n<p><strong>srflx<\/strong>\u00a0(server reflexive) &#8212; \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 IP, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0447\u0435\u0440\u0435\u0437 STUN<\/p>\n<\/li>\n<li>\n<p><strong>relay<\/strong>\u00a0&#8212; \u0430\u0434\u0440\u0435\u0441 \u043d\u0430 TURN-\u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0440\u0430\u0444\u0438\u043a<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u041a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u044b \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432\u00a0<strong>SDP<\/strong>\u00a0(Session Description Protocol)<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u0435 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u043f\u0440\u043e\u0432\u043e\u0434\u044f\u0442\u00a0<strong>connectivity checks<\/strong>\u00a0&#8212; \u043f\u0438\u043d\u0433\u0443\u044e\u0442 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u0430 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u0438\u043a\u0430<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0431\u0435\u0436\u0434\u0430\u0435\u0442 \u043f\u0430\u0440\u0430 \u0441 \u043b\u0443\u0447\u0448\u0435\u0439 \u0441\u0432\u044f\u0437\u043d\u043e\u0441\u0442\u044c\u044e<\/p>\n<\/li>\n<\/ol>\n<p><strong>STUN<\/strong>\u00a0(Session Traversal Utilities for NAT) &#8212; \u043b\u0451\u0433\u043a\u0438\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b. \u0411\u0440\u0430\u0443\u0437\u0435\u0440 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 STUN-\u0441\u0435\u0440\u0432\u0435\u0440, \u0442\u043e\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442: \u00ab\u0422\u0432\u043e\u0439 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 IP &#8212; \u0442\u0430\u043a\u043e\u0439-\u0442\u043e, \u043f\u043e\u0440\u0442 &#8212; \u0442\u0430\u043a\u043e\u0439-\u0442\u043e\u00bb. \u042d\u0442\u043e \u043a\u0430\u043a \u0441\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u043f\u0440\u043e\u0445\u043e\u0436\u0435\u0433\u043e, \u043a\u0430\u043a \u0442\u044b \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0448\u044c \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b.<\/p>\n<p><strong>TURN<\/strong>\u00a0(Traversal Using Relays around NAT) &#8212; \u0442\u044f\u0436\u0451\u043b\u0430\u044f \u0430\u0440\u0442\u0438\u043b\u043b\u0435\u0440\u0438\u044f. \u041a\u043e\u0433\u0434\u0430 \u043f\u0440\u044f\u043c\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e (symmetric NAT, \u0444\u0430\u0439\u0440\u0432\u043e\u043b), TURN-\u0441\u0435\u0440\u0432\u0435\u0440 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043f\u043e\u0441\u0440\u0435\u0434\u043d\u0438\u043a\u043e\u043c: \u0432\u0441\u0435 \u043c\u0435\u0434\u0438\u0430-\u043f\u0430\u043a\u0435\u0442\u044b \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0442 \u0447\u0435\u0440\u0435\u0437 \u043d\u0435\u0433\u043e. \u041c\u0435\u0434\u043b\u0435\u043d\u043d\u0435\u0435, \u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432\u0441\u0435\u0433\u0434\u0430.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/2e0\/767\/295\/2e0767295730ecf9d84c3df177a92030.jpeg\" alt=\"NAT-traversal \u043d\u0430 \u043f\u0430\u043b\u044c\u0446\u0430\u0445: (1) \u0437\u0430 NAT \u043d\u0435 \u0437\u043d\u0430\u0435\u0448\u044c \u0441\u0432\u043e\u0439 \u0430\u0434\u0440\u0435\u0441, (2) STUN \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u043a\u0430\u043a \u0442\u044b \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0448\u044c \u0441\u043d\u0430\u0440\u0443\u0436\u0438, (3) TURN \u043d\u043e\u0441\u0438\u0442 \u043f\u0430\u043a\u0435\u0442\u044b \u043c\u0435\u0436\u0434\u0443 \u0442\u0435\u043c\u0438, \u043a\u0442\u043e \u043d\u0435 \u0432\u0438\u0434\u0438\u0442 \u0434\u0440\u0443\u0433 \u0434\u0440\u0443\u0433\u0430\" width=\"2400\" height=\"1792\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/2e0\/767\/295\/2e0767295730ecf9d84c3df177a92030.jpeg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/2e0\/767\/295\/2e0767295730ecf9d84c3df177a92030.jpeg 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>NAT-traversal \u043d\u0430 \u043f\u0430\u043b\u044c\u0446\u0430\u0445: (1) \u0437\u0430 NAT \u043d\u0435 \u0437\u043d\u0430\u0435\u0448\u044c \u0441\u0432\u043e\u0439 \u0430\u0434\u0440\u0435\u0441, (2) STUN \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u043a\u0430\u043a \u0442\u044b \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0448\u044c \u0441\u043d\u0430\u0440\u0443\u0436\u0438, (3) TURN \u043d\u043e\u0441\u0438\u0442 \u043f\u0430\u043a\u0435\u0442\u044b \u043c\u0435\u0436\u0434\u0443 \u0442\u0435\u043c\u0438, \u043a\u0442\u043e \u043d\u0435 \u0432\u0438\u0434\u0438\u0442 \u0434\u0440\u0443\u0433 \u0434\u0440\u0443\u0433\u0430<\/figcaption><\/div>\n<\/figure>\n<p>\u041c\u044b \u043d\u0430\u0447\u0430\u043b\u0438 \u0431\u0435\u0437 STUN\/TURN:<\/p>\n<pre><code class=\"javascript\">const PC_CONFIG = { iceServers: [] };<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0411\u0440\u0430\u0443\u0437\u0435\u0440\u00a0<code>3002<\/code>\u00a0\u0441\u043e\u0431\u0440\u0430\u043b \u0442\u043e\u043b\u044c\u043a\u043e\u00a0<strong>host-\u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u043e\u0432<\/strong>:\u00a0<code>192.168.1.98<\/code>,\u00a0<code>10.8.0.10<\/code>\u00a0(VPN),\u00a0<code>fdbc:8196:...<\/code>\u00a0(IPv6 link-local). \u0412\u0441\u0435 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0435. Asterisk, \u0441\u0438\u0434\u044f\u0449\u0438\u0439 \u043d\u0430 VPS, \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0434\u043e \u043d\u0438\u0445 \u0434\u043e\u0441\u0442\u0443\u0447\u0430\u0442\u044c\u0441\u044f. ICE \u2192\u00a0<code>failed<\/code>. \u0417\u0432\u043e\u043d\u043e\u043a \u2192 \u0442\u0438\u0448\u0438\u043d\u0430.<\/p>\n<hr\/>\n<h3>\u0413\u043b\u0430\u0432\u0430 4. Google STUN &#8212; \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d<\/h3>\n<p>\u041f\u0435\u0440\u0432\u044b\u0439 \u0440\u0435\u0444\u043b\u0435\u043a\u0441: \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0435 STUN-\u0441\u0435\u0440\u0432\u0435\u0440\u044b Google.<\/p>\n<pre><code class=\"javascript\">iceServers: [  { urls: \"stun:stun.l.google.com:19302\" },  { urls: \"stun:stun1.l.google.com:19302\" }]<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0417\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e? \u041d\u0435\u0442.\u00a0<a href=\"http:\/\/stun.l.google.com\" rel=\"noopener nofollow\"><code>stun.l.google.com<\/code><\/a>\u00a0\u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d \u0432 \u0441\u0435\u0442\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0411\u0440\u0430\u0443\u0437\u0435\u0440 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u00a0<strong>srflx-\u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u0430<\/strong>, ICE \u0441\u043d\u043e\u0432\u0430 \u043d\u0430\u0448\u0451\u043b \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0435 \u0430\u0434\u0440\u0435\u0441\u0430.<\/p>\n<hr\/>\n<h3>\u0413\u043b\u0430\u0432\u0430 5. \u041f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u043c \u0441\u0432\u043e\u0439 Coturn<\/h3>\n<p>\u0415\u0441\u043b\u0438 Google STUN \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d &#8212; \u043f\u043e\u0434\u043d\u0438\u043c\u0435\u043c \u0441\u0432\u043e\u0439. \u041d\u0430 \u0442\u043e\u043c \u0436\u0435 VPS, \u0433\u0434\u0435 \u0436\u0438\u0432\u0451\u0442 Asterisk:<\/p>\n<pre><code class=\"bash\">docker run -d --name coturn --network host coturn\/coturn \\  -n --log-file=stdout \\  --listening-ip=0.0.0.0 \\  --external-ip=203.0.113.10 \\  --min-port=49152 --max-port=49252 \\  --lt-cred-mech --realm=voip.local --fingerprint \\  --user webrtc:S3cr3t_turn<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b:<\/p>\n<ul>\n<li>\n<p><code>--network host<\/code>\u00a0&#8212; \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0441\u0435\u0442\u044c \u0445\u043e\u0441\u0442\u0430 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e, \u0431\u0435\u0437 Docker NAT<\/p>\n<\/li>\n<li>\n<p><code>--external-ip<\/code>\u00a0&#8212; Coturn \u0437\u043d\u0430\u0435\u0442 \u0441\u0432\u043e\u0439 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 IP \u0434\u043b\u044f relay-\u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p><code>--lt-cred-mech<\/code>\u00a0&#8212; Long-Term Credential Mechanism (RFC 5389), \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0434\u043b\u044f TURN<\/p>\n<\/li>\n<li>\n<p><code>--min-port\/--max-port<\/code>\u00a0&#8212; \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d \u043f\u043e\u0440\u0442\u043e\u0432 \u0434\u043b\u044f relay-\u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0439<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0441\u0432\u043e\u0439 STUN+TURN \u043d\u0430\u00a0<code>203.0.113.10:3478<\/code>. \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u043a\u043e\u043d\u0444\u0438\u0433 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432:<\/p>\n<pre><code class=\"javascript\">iceServers: [  { urls: \"stun:203.0.113.10:3478\" },  {    urls: \"turn:203.0.113.10:3478?transport=udp\",    username: \"webrtc\",    credential: \"S3cr3t_turn\"  }]<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<hr\/>\n<h3>\u0413\u043b\u0430\u0432\u0430 6. \u041b\u043e\u0432\u0443\u0448\u043a\u0430 TCP TURN \u0438 \u043e\u0448\u0438\u0431\u043a\u0430 701<\/h3>\n<p>\u0417\u0432\u043e\u043d\u0438\u043c. ICE gathering \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f&#8230; \u0438 \u0437\u0430\u0432\u0438\u0441\u0430\u0435\u0442. \u0412 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 Chrome:<\/p>\n<pre><code>ice-candidate-error: url=turn:203.0.113.10:3478?transport=tcp code=701  text=Address not associated with the desired network interface.<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 TCP TURN \u043d\u0430\u0440\u044f\u0434\u0443 \u0441 UDP. Chrome \u0447\u0435\u0441\u0442\u043d\u043e \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0430\u043b\u043b\u043e\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c relay \u0447\u0435\u0440\u0435\u0437 TCP &#8212; \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0443 701. \u041d\u043e \u0432\u043e\u0442 \u043f\u043e\u0434\u0432\u043e\u0445:\u00a0<strong>Chrome \u043d\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u0442 ICE gathering, \u043f\u043e\u043a\u0430 \u043d\u0435 \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 TCP TURN<\/strong>. \u0412\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 \u0442\u0430\u0439\u043c\u0430\u0443\u0442 &#8212; \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u0441\u0435\u043a\u0443\u043d\u0434.<\/p>\n<p>\u0410 JsSIP \u0436\u0434\u0451\u0442\u00a0<code>iceGatheringState === \"complete\"<\/code>, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0432\u0441\u0435 \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u044b \u0432 SDP \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e. \u041f\u043e\u043a\u0430 gathering \u043d\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d &#8212; SDP \u043d\u0435 \u0443\u0445\u043e\u0434\u0438\u0442,\u00a0<code>200 OK<\/code>\u00a0\u043d\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f, Asterisk \u0441\u0447\u0438\u0442\u0430\u0435\u0442 \u0434\u043e 20 \u0438 \u0432\u0435\u0448\u0430\u0435\u0442 \u0442\u0440\u0443\u0431\u043a\u0443.<\/p>\n<p>\u0420\u0435\u0448\u0435\u043d\u0438\u0435: \u0443\u0431\u0440\u0430\u0442\u044c TCP TURN, \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e UDP.<\/p>\n<pre><code class=\"javascript\">urls: \"turn:203.0.113.10:3478?transport=udp\"<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<hr\/>\n<h3>\u0413\u043b\u0430\u0432\u0430 7.\u00a0event.ready()\u00a0&#8212; 40 \u0441\u0435\u043a\u0443\u043d\u0434 \u0432\u043f\u0443\u0441\u0442\u0443\u044e<\/h3>\n<p>TCP TURN \u0443\u0431\u0440\u0430\u043d. \u0417\u0432\u043e\u043d\u0438\u043c. ICE gathering&#8230; \u0432\u0441\u0451 \u0435\u0449\u0451 \u0432\u0438\u0441\u0438\u0442. Relay-\u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442 \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0437\u0430 \u0441\u0435\u043a\u0443\u043d\u0434\u0443, \u043d\u043e SDP \u0443\u0445\u043e\u0434\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0435\u0440\u0435\u0437\u00a0<strong>40 \u0441\u0435\u043a\u0443\u043d\u0434<\/strong>.<\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0442\u0430\u0439\u043c\u043b\u0430\u0439\u043d \u0432 \u043b\u043e\u0433:<\/p>\n<ul>\n<li>\n<p><code>23:01:43<\/code>\u00a0&#8212; relay-\u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442 \u0441\u043e\u0431\u0440\u0430\u043d<\/p>\n<\/li>\n<li>\n<p><code>23:02:23<\/code>\u00a0&#8212; SDP \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d<\/p>\n<\/li>\n<\/ul>\n<p>40 \u0441\u0435\u043a\u0443\u043d\u0434 \u0440\u0430\u0437\u043d\u0438\u0446\u044b. \u0413\u0434\u0435 \u043e\u043d\u0438 \u0442\u0435\u0440\u044f\u044e\u0442\u0441\u044f?<\/p>\n<p>\u041e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u0432 JsSIP \u0435\u0441\u0442\u044c \u0445\u0438\u0442\u0440\u043e\u0441\u0442\u044c. \u0421\u043e\u0431\u044b\u0442\u0438\u0435\u00a0<code>icecandidate<\/code>\u00a0\u043d\u0430\u00a0<strong>\u0441\u0435\u0441\u0441\u0438\u0438<\/strong>\u00a0(\u043d\u0435 \u043d\u0430 RTCPeerConnection!) \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u043c\u0435\u0442\u043e\u0434\u043e\u043c\u00a0<code>event.ready()<\/code>. \u0415\u0441\u043b\u0438 \u0432\u044b \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043b\u0438\u0441\u044c \u043d\u0430 \u044d\u0442\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0438\u00a0<strong>\u043d\u0435 \u0432\u044b\u0437\u0432\u0430\u043b\u0438<\/strong>\u00a0<code>ready()<\/code>\u00a0&#8212; JsSIP \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u0443\u0435\u0442 \u044d\u0442\u043e \u043a\u0430\u043a \u00ab\u043f\u043e\u0434\u043e\u0436\u0434\u0438, \u044f \u0435\u0449\u0451 \u0434\u0443\u043c\u0430\u044e\u00bb. \u0418 \u0436\u0434\u0451\u0442. \u0421\u0432\u043e\u0439 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 \u0442\u0430\u0439\u043c\u0430\u0443\u0442 &#8212; ~40 \u0441\u0435\u043a\u0443\u043d\u0434.<\/p>\n<p>\u041d\u0430\u0448 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"javascript\">session.on(\"icecandidate\", (ev) =&gt; {  log(\"ICE candidate generated\");  \/\/ \u0417\u0430\u0431\u044b\u043b\u0438 ev.ready()!});<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u0430 \u0438 \u043d\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u043b\u0438 JsSIP, \u0447\u0442\u043e \u043e\u043d \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442\u044c. \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0442\u0435\u0440\u043f\u0435\u043b\u0438\u0432\u043e \u0436\u0434\u0430\u043b\u0430 40 \u0441\u0435\u043a\u0443\u043d\u0434, \u043f\u043e\u0442\u043e\u043c \u0441\u0434\u0430\u0432\u0430\u043b\u0430\u0441\u044c \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u043b\u0430 SDP.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/87e\/54f\/9a2\/87e54f9a2a9cc94820d9d6a728348ac1.jpeg\" alt=\"JsSIP \u0442\u0435\u0440\u043f\u0435\u043b\u0438\u0432\u043e \u0436\u0434\u0451\u0442, \u043f\u043e\u043a\u0430 \u043a\u0442\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u0432\u044b\u0437\u043e\u0432\u0435\u0442 ready()\" width=\"2400\" height=\"1792\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/87e\/54f\/9a2\/87e54f9a2a9cc94820d9d6a728348ac1.jpeg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/87e\/54f\/9a2\/87e54f9a2a9cc94820d9d6a728348ac1.jpeg 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>JsSIP \u0442\u0435\u0440\u043f\u0435\u043b\u0438\u0432\u043e \u0436\u0434\u0451\u0442, \u043f\u043e\u043a\u0430 \u043a\u0442\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u0432\u044b\u0437\u043e\u0432\u0435\u0442 ready()<\/figcaption><\/div>\n<\/figure>\n<p>\u0418\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 &#8212; \u043e\u0434\u043d\u0430 \u0441\u0442\u0440\u043e\u043a\u0430:<\/p>\n<pre><code class=\"javascript\">session.on(\"icecandidate\", (ev) =&gt; {  log(\"ICE candidate generated\");  if (ev &amp;&amp; typeof ev.ready === \"function\") ev.ready();});<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e INVITE \u0438\u00a0<code>200 OK<\/code>\u00a0\u0441\u0442\u0430\u043b\u0438 \u0443\u043b\u0435\u0442\u0430\u0442\u044c \u0437\u0430 1\u20132 \u0441\u0435\u043a\u0443\u043d\u0434\u044b.<\/p>\n<hr\/>\n<h3>\u0413\u043b\u0430\u0432\u0430 8.\u00a0ice_host_candidates\u00a0&#8212; \u0441\u0435\u043a\u0446\u0438\u044f, \u0430 \u043d\u0435 \u043a\u043b\u044e\u0447<\/h3>\n<p>\u0417\u0432\u043e\u043d\u043e\u043a \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f!\u00a0<code>session accepted<\/code>,\u00a0<code>session confirmed<\/code>. \u041d\u043e\u00a0<code>out_packets=0<\/code>. \u0422\u0438\u0448\u0438\u043d\u0430 \u0432 \u044d\u0444\u0438\u0440\u0435.<\/p>\n<p>\u0421\u043c\u043e\u0442\u0440\u0438\u043c SDP, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 Asterisk \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0443\u00a0<code>3002<\/code>:<\/p>\n<pre><code>c=IN IP4 192.168.0.129a=candidate:Hc0a80081 1 UDP 2130706431 192.168.0.129 18008 typ hosta=candidate:Hac110001 1 UDP 2130706431 172.17.0.1 18008 typ host<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><code>192.168.0.129<\/code>\u00a0&#8212; \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0439 IP VPS (\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u00a0<code>ens3<\/code>).\u00a0<code>172.17.0.1<\/code>\u00a0&#8212; Docker bridge. \u041e\u0431\u0430 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0438\u0437 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430. \u0411\u0440\u0430\u0443\u0437\u0435\u0440 \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c RTP \u043d\u0430 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0435 \u0430\u0434\u0440\u0435\u0441\u0430 &#8212; \u0438, \u0440\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u043e\u0445\u043e\u0434\u0438\u0442.<\/p>\n<p>\u0412\u00a0<code>rtp.conf<\/code>\u00a0\u0443 \u043d\u0430\u0441 \u0431\u044b\u043b\u043e:<\/p>\n<pre><code>[general]ice_host_candidate=203.0.113.10<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e. \u0427\u0438\u0442\u0430\u0435\u043c\u00a0<a href=\"https:\/\/github.com\/asterisk\/asterisk\/blob\/master\/configs\/samples\/rtp.conf.sample\" rel=\"noopener nofollow\">\u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439\u00a0<code>rtp.conf.sample<\/code><\/a>\u00a0\u0438\u0437 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f Asterisk \u0438 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0435\u043c:\u00a0<code>ice_host_candidates<\/code>\u00a0&#8212; \u044d\u0442\u043e\u00a0<strong>\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0441\u0435\u043a\u0446\u0438\u044f<\/strong>, \u0430 \u043d\u0435 \u043a\u043b\u044e\u0447 \u0432\u00a0<code>[general]<\/code>. \u0418 \u0444\u043e\u0440\u043c\u0430\u0442 \u043c\u0430\u043f\u043f\u0438\u043d\u0433\u0430:<\/p>\n<pre><code>[ice_host_candidates]192.168.0.129 =&gt; 203.0.113.10<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u042d\u0442\u043e \u0433\u043e\u0432\u043e\u0440\u0438\u0442 Asterisk: \u00ab\u041a\u043e\u0433\u0434\u0430 \u0442\u044b \u0432\u0438\u0434\u0438\u0448\u044c \u0441\u0432\u043e\u0439 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0430\u0434\u0440\u0435\u0441\u00a0<code>192.168.0.129<\/code>\u00a0\u0432 ICE-\u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u0430\u0445 &#8212; \u0437\u0430\u043c\u0435\u043d\u0438 \u0435\u0433\u043e \u043d\u0430 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439\u00a0<code>203.0.113.10<\/code>\u00bb.<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f SDP \u0441\u0442\u0430\u043b \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u043c:<\/p>\n<pre><code>a=candidate:H59684ac5 1 UDP 2130706431 203.0.113.10 18008 typ host<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<hr\/>\n<h3>\u0413\u043b\u0430\u0432\u0430 9.\u00a0relay-only\u00a0\u0438 \u043f\u0435\u0442\u043b\u044f 403<\/h3>\n<p>\u041a \u044d\u0442\u043e\u043c\u0443 \u043c\u043e\u043c\u0435\u043d\u0442\u0443 \u043c\u044b \u0443\u0436\u0435 \u0443\u0441\u0442\u0430\u043b\u0438 \u043e\u0442 \u0434\u043e\u043b\u0433\u043e\u0433\u043e ICE gathering (Chrome \u043f\u0435\u0440\u0435\u0431\u0438\u0440\u0430\u043b host, srflx, relay \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u044b \u043f\u043e \u0432\u0441\u0435\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430\u043c &#8212; WiFi, VPN, IPv6). \u0420\u0435\u0448\u0435\u043d\u0438\u0435:\u00a0<code>iceTransportPolicy: \"relay\"<\/code>\u00a0&#8212; \u0444\u043e\u0440\u0441\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u00a0<strong>\u0442\u043e\u043b\u044c\u043a\u043e<\/strong>\u00a0TURN relay.<\/p>\n<pre><code class=\"javascript\">const PC_CONFIG = {  iceTransportPolicy: \"relay\",  iceServers: [{ urls: \"turn:203.0.113.10:3478?transport=udp\", ... }]};<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>ICE gathering \u0441\u0442\u0430\u043b \u043c\u043e\u043b\u043d\u0438\u0435\u043d\u043e\u0441\u043d\u044b\u043c: \u043e\u0434\u0438\u043d relay-\u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442, \u0433\u043e\u0442\u043e\u0432\u043e. \u0417\u0432\u043e\u043d\u043e\u043a \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0437\u0430 \u0441\u0435\u043a\u0443\u043d\u0434\u044b. \u0418\u0434\u0435\u0430\u043b\u044c\u043d\u043e?<\/p>\n<p>\u041d\u0435\u0442.\u00a0<code>out_packets=0<\/code>. \u041e\u043f\u044f\u0442\u044c.<\/p>\n<p>\u0412\u043a\u043b\u044e\u0447\u0430\u0435\u043c RTP debug \u043d\u0430 Asterisk \u0438 \u0432\u0438\u0434\u0438\u043c \u0432 \u043b\u043e\u0433\u0430\u0445:<\/p>\n<pre><code>pjproject: CreatePermission failed for IP 203.0.113.10: 403\/Forbidden IP<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0427\u0442\u043e \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e: \u043c\u044b \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438\u00a0<code>turnaddr=127.0.0.1:3478<\/code>\u00a0\u0432\u00a0<code>rtp.conf<\/code>\u00a0Asterisk, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u0442\u043e\u0436\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u043b relay-\u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u044b. Asterisk \u0430\u043b\u043b\u043e\u0446\u0438\u0440\u043e\u0432\u0430\u043b relay \u043d\u0430 Coturn (\u0430\u0434\u0440\u0435\u0441\u00a0<code>203.0.113.10:49160<\/code>). \u0411\u0440\u0430\u0443\u0437\u0435\u0440 \u0442\u043e\u0436\u0435 \u0430\u043b\u043b\u043e\u0446\u0438\u0440\u043e\u0432\u0430\u043b relay \u043d\u0430 \u0442\u043e\u043c \u0436\u0435 Coturn (<code>203.0.113.10:49202<\/code>).<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c Asterisk \u0447\u0435\u0440\u0435\u0437 \u0441\u0432\u043e\u0439 TURN relay \u0445\u043e\u0447\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043f\u0430\u043a\u0435\u0442 \u043d\u0430\u00a0<code>203.0.113.10:49202<\/code>\u00a0(relay \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430). \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043e\u043d \u043f\u0440\u043e\u0441\u0438\u0442 Coturn: \u00ab\u0421\u043e\u0437\u0434\u0430\u0439 permission \u043d\u0430 IP\u00a0<code>203.0.113.10<\/code>\u00bb. Coturn \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442:\u00a0<strong>403 Forbidden<\/strong>. \u041f\u043e\u0447\u0435\u043c\u0443? \u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e\u00a0<code>203.0.113.10<\/code>\u00a0&#8212; \u044d\u0442\u043e\u00a0<strong>\u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 IP Coturn<\/strong>. TURN-\u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0430\u0435\u0442 relay-\u0438\u0442\u044c \u0442\u0440\u0430\u0444\u0438\u043a \u0441\u0430\u043c\u043e\u043c\u0443 \u0441\u0435\u0431\u0435 &#8212; \u044d\u0442\u043e \u0437\u0430\u0449\u0438\u0442\u0430 \u043e\u0442 \u043f\u0435\u0442\u0435\u043b\u044c.<\/p>\n<p>\u041c\u044b \u043f\u043e\u043f\u0430\u043b\u0438 \u0432 \u043b\u043e\u0432\u0443\u0448\u043a\u0443: \u043e\u0431\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 (Asterisk \u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440) \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 TURN-\u0441\u0435\u0440\u0432\u0435\u0440, \u0438 \u0438\u0445 relay-\u0430\u0434\u0440\u0435\u0441\u0430 \u0431\u044b\u043b\u0438 \u043d\u0430 \u043e\u0434\u043d\u043e\u043c IP. TURN \u043d\u0435 \u0443\u043c\u0435\u0435\u0442 \u043f\u0440\u043e\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0440\u0430\u0444\u0438\u043a \u043c\u0435\u0436\u0434\u0443 \u0434\u0432\u0443\u043c\u044f \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u044f\u043c\u0438 \u043d\u0430 \u0441\u0435\u0431\u0435 \u0441\u0430\u043c\u043e\u043c.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/acf\/37d\/31d\/acf37d31d9f38cf4d05e8c8d916e7da6.jpeg\" alt=\"\u041f\u0435\u0442\u043b\u044f: \u0434\u0432\u0430 relay \u043d\u0430 \u043e\u0434\u043d\u043e\u043c TURN-\u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0443\u043f\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0432 403 Forbidden\" width=\"2400\" height=\"1792\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/acf\/37d\/31d\/acf37d31d9f38cf4d05e8c8d916e7da6.jpeg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/acf\/37d\/31d\/acf37d31d9f38cf4d05e8c8d916e7da6.jpeg 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041f\u0435\u0442\u043b\u044f: \u0434\u0432\u0430 relay \u043d\u0430 \u043e\u0434\u043d\u043e\u043c TURN-\u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0443\u043f\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0432 403 Forbidden<\/figcaption><\/div>\n<\/figure>\n<p>\u0420\u0435\u0448\u0435\u043d\u0438\u0435: \u0443\u0431\u0440\u0430\u0442\u044c TURN \u0443 Asterisk (\u0435\u043c\u0443 \u043d\u0435 \u043d\u0443\u0436\u0435\u043d relay &#8212; \u043e\u043d \u043d\u0430 \u0442\u043e\u043c \u0436\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u0447\u0442\u043e \u0438 Coturn) \u0438 \u0443\u0431\u0440\u0430\u0442\u044c\u00a0<code>relay-only<\/code>\u00a0\u0443 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u0432. Asterisk \u0440\u0435\u043a\u043b\u0430\u043c\u0438\u0440\u0443\u0435\u0442 \u0441\u0432\u043e\u0439 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 IP \u0447\u0435\u0440\u0435\u0437\u00a0<code>ice_host_candidates<\/code>, \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 srflx-\u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442 \u0447\u0435\u0440\u0435\u0437 STUN, \u0438 \u043e\u043d\u0438 \u043d\u0430\u0445\u043e\u0434\u044f\u0442 \u0434\u0440\u0443\u0433 \u0434\u0440\u0443\u0433\u0430 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e.<\/p>\n<hr\/>\n<h3>\u0413\u043b\u0430\u0432\u0430 10. \u0410\u0443\u0434\u0438\u043e \u043f\u043e\u0448\u043b\u043e<\/h3>\n<p>\u0424\u0438\u043d\u0430\u043b\u044c\u043d\u0430\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f:<\/p>\n<p><strong>\u041a\u043b\u0438\u0435\u043d\u0442\u044b (\u0431\u0440\u0430\u0443\u0437\u0435\u0440):<\/strong><\/p>\n<pre><code class=\"javascript\">const PC_CONFIG = {  iceServers: [    { urls: \"stun:203.0.113.10:3478\" },    {      urls: \"turn:203.0.113.10:3478?transport=udp\",      username: \"webrtc\",      credential: \"S3cr3t_turn\"    }  ]};<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>Asterisk (<\/strong><code><strong>rtp.conf<\/strong><\/code><strong>):<\/strong><\/p>\n<pre><code>[general]rtpstart=18000rtpend=18100[ice_host_candidates]192.168.0.129 =&gt; 203.0.113.10<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0417\u0432\u043e\u043d\u0438\u043c. \u0421\u043c\u043e\u0442\u0440\u0438\u043c\u00a0<code>pjsip show channelstats<\/code>:<\/p>\n<pre><code>BridgeId  Channel     UpTime  Codec  Recv   Lost  Tx     Lost  RTTfcc03999  3001        00:24   opus   1132   2%    1141   2%    0.022fcc03999  3002        00:24   opus   1152   1%    1132   2%    0.022<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>RTP debug:<\/p>\n<pre><code>Got  RTP packet from 198.51.100.23:65488 (type 111, seq 003634, len 049)Sent RTP packet to   198.51.100.23:56199 (via ICE) (type 111, seq 064699, len 049)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u0430\u043a\u0435\u0442\u044b \u0438\u0434\u0443\u0442 \u0432 \u043e\u0431\u0435 \u0441\u0442\u043e\u0440\u043e\u043d\u044b. Opus, 48 kHz. \u041f\u043e\u0442\u0435\u0440\u0438 ~1\u20132% (\u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430). RTT 22 \u043c\u0441. \u0413\u043e\u043b\u043e\u0441 \u0441\u043b\u044b\u0448\u0435\u043d.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/04c\/bb0\/ea3\/04cbb0ea35b67b66dbce8b430d0a2f07.jpeg\" alt=\"\u0410\u0443\u0434\u0438\u043e \u043d\u0430\u043a\u043e\u043d\u0435\u0446 \u0438\u0434\u0451\u0442 \u0432 \u043e\u0431\u0435 \u0441\u0442\u043e\u0440\u043e\u043d\u044b\" width=\"2400\" height=\"1792\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/04c\/bb0\/ea3\/04cbb0ea35b67b66dbce8b430d0a2f07.jpeg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/04c\/bb0\/ea3\/04cbb0ea35b67b66dbce8b430d0a2f07.jpeg 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0410\u0443\u0434\u0438\u043e \u043d\u0430\u043a\u043e\u043d\u0435\u0446 \u0438\u0434\u0451\u0442 \u0432 \u043e\u0431\u0435 \u0441\u0442\u043e\u0440\u043e\u043d\u044b<\/figcaption><\/div>\n<\/figure>\n<hr\/>\n<h3>\u042d\u043f\u0438\u043b\u043e\u0433: \u0427\u0435\u043c\u0443 \u043d\u0430\u0441 \u043d\u0430\u0443\u0447\u0438\u043b \u043e\u0434\u0438\u043d \u0437\u0432\u043e\u043d\u043e\u043a<\/h3>\n<p>\u041e\u0434\u0438\u043d WebRTC-\u0437\u0432\u043e\u043d\u043e\u043a &#8212; \u044d\u0442\u043e \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u043e\u0432, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0445 \u0432 \u0443\u043d\u0438\u0441\u043e\u043d:<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u0421\u043b\u043e\u0439<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0420\u043e\u043b\u044c<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0421\u0438\u0433\u043d\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f<\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>SIP<\/strong>\u00a0\u043f\u043e\u0432\u0435\u0440\u0445\u00a0<strong>WSS<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430\/\u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0437\u0432\u043e\u043d\u043a\u0430<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0435\u0441\u0441\u0438\u0438<\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>SDP<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041e\u0431\u043c\u0435\u043d \u043a\u043e\u0434\u0435\u043a\u0430\u043c\u0438, \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u0430\u043c\u0438, fingerprint&#8217;\u0430\u043c\u0438<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">NAT-traversal<\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>ICE<\/strong>\u00a0+\u00a0<strong>STUN<\/strong>\u00a0+\u00a0<strong>TURN<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041f\u043e\u0438\u0441\u043a \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0430 \u0434\u043b\u044f \u043c\u0435\u0434\u0438\u0430<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0428\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>DTLS<\/strong>\u00a0(\u0445\u044d\u043d\u0434\u0448\u0435\u0439\u043a) +\u00a0<strong>SRTP<\/strong>\u00a0(\u043c\u0435\u0434\u0438\u0430)<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041a\u043e\u043d\u0444\u0438\u0434\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u041c\u0435\u0434\u0438\u0430-\u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442<\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>RTP<\/strong>\u00a0\/\u00a0<strong>RTCP<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0414\u043e\u0441\u0442\u0430\u0432\u043a\u0430 \u0438 \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433 \u0430\u0443\u0434\u0438\u043e<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u041a\u043e\u0434\u0435\u043a<\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>Opus<\/strong>\u00a0(48 kHz, FEC, \u0430\u0434\u0430\u043f\u0442\u0438\u0432\u043d\u044b\u0439)<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0421\u0436\u0430\u0442\u0438\u0435 \u0433\u043e\u043b\u043e\u0441\u0430<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>\u0418 \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c \u0441\u043b\u043e\u0435 \u043c\u043e\u0436\u0435\u0442 \u0441\u043b\u043e\u043c\u0430\u0442\u044c\u0441\u044f \u0447\u0442\u043e \u0443\u0433\u043e\u0434\u043d\u043e:<\/p>\n<ul>\n<li>\n<p><strong>SDP \u0431\u0435\u0437 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e\u0433\u043e IP<\/strong>\u00a0&#8212; ICE \u043d\u0435 \u043d\u0430\u0439\u0434\u0451\u0442 \u043c\u0430\u0440\u0448\u0440\u0443\u0442<\/p>\n<\/li>\n<li>\n<p><strong>\u0417\u0430\u0431\u044b\u0442\u044b\u0439\u00a0<\/strong><code><strong>event.ready()<\/strong><\/code>\u00a0&#8212; JsSIP \u0437\u0430\u0432\u0438\u0441\u043d\u0435\u0442 \u043d\u0430 40 \u0441\u0435\u043a\u0443\u043d\u0434<\/p>\n<\/li>\n<li>\n<p><strong>TCP TURN \u0437\u0430 \u0444\u0430\u0439\u0440\u0432\u043e\u043b\u043e\u043c<\/strong>\u00a0&#8212; Chrome \u043d\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442 ICE gathering<\/p>\n<\/li>\n<li>\n<p><strong>\u0414\u0432\u0430 relay \u043d\u0430 \u043e\u0434\u043d\u043e\u043c TURN<\/strong>\u00a0&#8212; \u043f\u0435\u0442\u043b\u044f \u0441 403 Forbidden<\/p>\n<\/li>\n<li>\n<p><strong>\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u043a\u043e\u043d\u0444\u0438\u0433\u0430<\/strong>\u00a0&#8212; Asterisk \u043c\u043e\u043b\u0447\u0430 \u043f\u0440\u043e\u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0443<\/p>\n<\/li>\n<\/ul>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u044d\u0442\u0438\u0445 \u0431\u0430\u0433\u043e\u0432 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b \u043a\u0430\u043a \u00ab\u043d\u0435\u0442 \u0437\u0432\u0443\u043a\u0430\u00bb. \u041e\u0434\u0438\u043d \u0441\u0438\u043c\u043f\u0442\u043e\u043c, \u043f\u044f\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0445 \u043f\u0440\u0438\u0447\u0438\u043d. \u041a\u043b\u0430\u0441\u0441\u0438\u043a\u0430 VoIP.<\/p>\n<hr\/>\n<h3>\u0428\u043f\u0430\u0440\u0433\u0430\u043b\u043a\u0430: \u0441\u043b\u043e\u0432\u0430\u0440\u044c \u0442\u0435\u0440\u043c\u0438\u043d\u043e\u0432<\/h3>\n<ul>\n<li>\n<p><strong>WebRTC<\/strong>\u00a0&#8212; Web Real-Time Communication, API \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u0434\u043b\u044f \u0430\u0443\u0434\u0438\u043e\/\u0432\u0438\u0434\u0435\u043e\/\u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438<\/p>\n<\/li>\n<li>\n<p><strong>SIP<\/strong>\u00a0&#8212; Session Initiation Protocol, \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f VoIP-\u0441\u0435\u0441\u0441\u0438\u044f\u043c\u0438<\/p>\n<\/li>\n<li>\n<p><strong>SDP<\/strong>\u00a0&#8212; Session Description Protocol, \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043c\u0435\u0434\u0438\u0430-\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432<\/p>\n<\/li>\n<li>\n<p><strong>ICE<\/strong>\u00a0&#8212; Interactive Connectivity Establishment, \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u043f\u043e\u0438\u0441\u043a\u0430 \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0430<\/p>\n<\/li>\n<li>\n<p><strong>STUN<\/strong>\u00a0&#8212; Session Traversal Utilities for NAT, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e\u0433\u043e \u0430\u0434\u0440\u0435\u0441\u0430<\/p>\n<\/li>\n<li>\n<p><strong>TURN<\/strong>\u00a0&#8212; Traversal Using Relays around NAT, \u043f\u0440\u043e\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0435\u0434\u0438\u0430 \u0447\u0435\u0440\u0435\u0437 \u0441\u0435\u0440\u0432\u0435\u0440<\/p>\n<\/li>\n<li>\n<p><strong>Coturn<\/strong>\u00a0&#8212; \u043e\u043f\u0435\u043d\u0441\u043e\u0440\u0441\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f STUN\/TURN-\u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/p>\n<\/li>\n<li>\n<p><strong>RTP\/RTCP<\/strong>\u00a0&#8212; Real-time Transport Protocol \/ RTP Control Protocol<\/p>\n<\/li>\n<li>\n<p><strong>DTLS-SRTP<\/strong>\u00a0&#8212; \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0435\u0434\u0438\u0430 \u0432 WebRTC (DTLS \u0434\u043b\u044f \u043a\u043b\u044e\u0447\u0435\u0439, SRTP \u0434\u043b\u044f \u043f\u043e\u0442\u043e\u043a\u0430)<\/p>\n<\/li>\n<li>\n<p><strong>Opus<\/strong>\u00a0&#8212; \u043a\u043e\u0434\u0435\u043a \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442 WebRTC (RFC 6716)<\/p>\n<\/li>\n<li>\n<p><strong>G.711 (PCMU\/PCMA)<\/strong>\u00a0&#8212; \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u043d\u044b\u0439 \u043a\u043e\u0434\u0435\u043a, 64 kbps, \u0431\u0435\u0437 \u0441\u0436\u0430\u0442\u0438\u044f<\/p>\n<\/li>\n<li>\n<p><strong>G.722<\/strong>\u00a0&#8212; \u0448\u0438\u0440\u043e\u043a\u043e\u043f\u043e\u043b\u043e\u0441\u043d\u044b\u0439 \u043a\u043e\u0434\u0435\u043a (HD Voice), 48\/56\/64 kbps<\/p>\n<\/li>\n<li>\n<p><strong>AMR<\/strong>\u00a0&#8212; Adaptive Multi-Rate, \u043a\u043e\u0434\u0435\u043a \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0441\u0435\u0442\u0435\u0439 (GSM\/3G)<\/p>\n<\/li>\n<li>\n<p><strong>Asterisk<\/strong>\u00a0&#8212; \u043e\u043f\u0435\u043d\u0441\u043e\u0440\u0441\u043d\u0430\u044f \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u043d\u0430\u044f \u0441\u0442\u0430\u043d\u0446\u0438\u044f (PBX)<\/p>\n<\/li>\n<li>\n<p><strong>PJSIP<\/strong>\u00a0&#8212; SIP-\u0441\u0442\u0435\u043a \u0432\u043d\u0443\u0442\u0440\u0438 Asterisk<\/p>\n<\/li>\n<li>\n<p><strong>JsSIP<\/strong>\u00a0&#8212; JavaScript SIP-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430<\/p>\n<\/li>\n<li>\n<p><strong>WSS<\/strong>\u00a0&#8212; WebSocket Secure, \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 WebSocket \u0434\u043b\u044f SIP-\u0441\u0438\u0433\u043d\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438<\/p>\n<\/li>\n<li>\n<p><strong>NAT<\/strong>\u00a0&#8212; Network Address Translation, \u0442\u0440\u0430\u043d\u0441\u043b\u044f\u0446\u0438\u044f \u0430\u0434\u0440\u0435\u0441\u043e\u0432 (\u043f\u0440\u0438\u0447\u0438\u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0430 VoIP-\u043f\u0440\u043e\u0431\u043b\u0435\u043c)<\/p>\n<\/li>\n<li>\n<p><strong>Offer\/Answer model<\/strong>\u00a0&#8212; \u043c\u043e\u0434\u0435\u043b\u044c SDP-\u043e\u0431\u043c\u0435\u043d\u0430: \u043e\u0434\u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0430 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 (offer), \u0434\u0440\u0443\u0433\u0430\u044f \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 (answer)<\/p>\n<\/li>\n<\/ul>\n<hr\/>\n<p><em>\u041d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u043f\u043e \u043c\u043e\u0442\u0438\u0432\u0430\u043c \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0434\u0435\u0431\u0430\u0433\u0430 \u0432 23:00, \u043a\u043e\u0433\u0434\u0430 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u043c \u0441\u0432\u0435\u0442\u0430 \u0431\u044b\u043b\u0438 \u0434\u0432\u0430 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0430 \u0441 docker logs.<\/em><\/p>\n<\/div>\n<p>\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/1084902\/\">https:\/\/habr.com\/ru\/articles\/1084902\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0417\u0430\u0434\u0430\u0447\u0430 \u0437\u0432\u0443\u0447\u0430\u043b\u0430 \u043d\u0435\u0432\u0438\u043d\u043d\u043e: \u0434\u0432\u0430 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430, \u043a\u043d\u043e\u043f\u043a\u0430 \u00abCall\u00bb, \u0433\u043e\u043b\u043e\u0441 \u0432 \u043e\u0431\u0435 \u0441\u0442\u043e\u0440\u043e\u043d\u044b. \u041f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c &#8212; Asterisk \u043d\u0430 VPS, WebRTC \u0432 Chrome, SIP \u043f\u043e\u0432\u0435\u0440\u0445 WebSocket. \u0427\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0439\u0442\u0438 \u043d\u0435 \u0442\u0430\u043a?\u0412\u0441\u0451. \u041f\u044f\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0445 \u0431\u0430\u0433\u043e\u0432 \u0441 \u043e\u0434\u043d\u0438\u043c \u0438 \u0442\u0435\u043c \u0436\u0435 \u0441\u0438\u043c\u043f\u0442\u043e\u043c\u043e\u043c &#8212; \u00ab\u043d\u0435\u0442 \u0437\u0432\u0443\u043a\u0430\u00bb. \u042d\u0442\u043e \u0434\u0435\u0442\u0435\u043a\u0442\u0438\u0432\u043d\u0430\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u0437\u0432\u043e\u043d\u043a\u0430: \u0432\u0441\u0435 \u0431\u0430\u0433\u0438 \u0440\u0435\u0430\u043b\u044c\u043d\u044b, \u0432\u0441\u0435 \u0433\u0440\u0430\u0431\u043b\u0438 &#8212; \u043d\u0430\u0448\u0438. IP-\u0430\u0434\u0440\u0435\u0441\u0430 \u0438 \u043a\u0440\u0435\u0434\u044b \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u0437\u0430\u043c\u0435\u043d\u0435\u043d\u044b \u043d\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435.\u041e\u0445\u043e\u0442\u0430 \u043d\u0430 \u043f\u0440\u043e\u043f\u0430\u0432\u0448\u0438\u0439 \u0437\u0432\u0443\u043a\u0413\u043b\u0430\u0432\u0430 1. \u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0437\u0430\u0441\u043b\u0443\u0436\u0438\u043b\u0438\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u0441\u0435\u0431\u0435 \u0441\u0445\u0435\u043c\u0443. VPS \u0441 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u043c IP\u00a0203.0.113.10. \u041d\u0430 \u043d\u0451\u043c \u043a\u0440\u0443\u0442\u0438\u0442\u0441\u044f Docker-\u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0441\u00a0Asterisk 22.8\u00a0&#8212; \u043e\u043f\u0435\u043d\u0441\u043e\u0440\u0441\u043d\u043e\u0439 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u043d\u0446\u0438\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0443\u043c\u0435\u0435\u0442 \u0432\u0441\u0451: \u043e\u0442 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0445 SIP-\u0437\u0432\u043e\u043d\u043a\u043e\u0432 \u0434\u043e WebRTC. \u0420\u044f\u0434\u043e\u043c &#8212;\u00a0Coturn, STUN\/TURN-\u0441\u0435\u0440\u0432\u0435\u0440, \u0442\u043e\u0436\u0435 \u0432 Docker, \u0432 host-\u0440\u0435\u0436\u0438\u043c\u0435.\u041d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 &#8212; \u0434\u0432\u0430 HTML-\u0444\u0430\u0439\u043b\u0430.\u00a0index.html\u00a0&#8212; \u0437\u0432\u043e\u043d\u044f\u0449\u0438\u0439 (\u0430\u0431\u043e\u043d\u0435\u043d\u0442\u00a03001).\u00a03002.html\u00a0&#8212; \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u0439 \u0441 \u0430\u0432\u0442\u043e-\u043e\u0442\u0432\u0435\u0442\u043e\u043c. \u041e\u0431\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u00a0JsSIP\u00a0&#8212; JavaScript-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 SIP-\u0441\u0442\u0435\u043a \u043f\u0440\u044f\u043c\u043e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435. SIP-\u0441\u0438\u0433\u043d\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438\u0434\u0451\u0442 \u043f\u043e\u00a0WSS\u00a0(WebSocket Secure) \u0447\u0435\u0440\u0435\u0437 \u043f\u043e\u0440\u0442 8089. \u041c\u0435\u0434\u0438\u0430 &#8212; \u043f\u043e\u00a0RTP\u00a0(Real-time Transport Protocol), \u0437\u0430\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c\u0443 \u0432\u00a0DTLS-SRTP, \u0447\u0435\u0440\u0435\u0437 \u043f\u043e\u0440\u0442\u044b 18000\u201318100 UDP.\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430: \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u044b, Asterisk \u0438 Coturn \u043d\u0430 VPS, \u0441\u0438\u0433\u043d\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e WSS, \u043c\u0435\u0434\u0438\u0430 \u043f\u043e RTP\u041a\u043e\u0434\u0435\u043a &#8212;\u00a0Opus\u00a0(48 kHz, 2 \u043a\u0430\u043d\u0430\u043b\u0430). \u041d\u0435 MP3, \u043d\u0435 AMR, \u043d\u0435 G.711. Opus &#8212; \u044d\u0442\u043e \u043a\u043e\u0434\u0435\u043a, \u0440\u043e\u0436\u0434\u0451\u043d\u043d\u044b\u0439 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438: \u0430\u0434\u0430\u043f\u0442\u0438\u0432\u043d\u044b\u0439 \u0431\u0438\u0442\u0440\u0435\u0439\u0442, \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u0430\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0446\u0438\u044f \u043e\u0448\u0438\u0431\u043e\u043a (FEC), \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0430 \u043e\u0442 5 \u043c\u0441. \u0412 \u043c\u0438\u0440\u0435 VoIP \u0435\u0441\u0442\u044c \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u043a\u043e\u0434\u0435\u043a\u043e\u0432 &#8212;\u00a0G.711\u00a0(\u03bc-law\/A-law, \u043e\u043d \u0436\u0435 PCMU\/PCMA) \u0434\u043b\u044f \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u0438 \u0441 PSTN,\u00a0G.722\u00a0\u0434\u043b\u044f HD-\u0433\u043e\u043b\u043e\u0441\u0430,\u00a0AMR\u00a0\u0432 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0441\u0435\u0442\u044f\u0445,\u00a0G.729\u00a0\u0441 \u0435\u0433\u043e \u043f\u043b\u0430\u0442\u043d\u044b\u043c\u0438 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u044f\u043c\u0438. \u041d\u043e \u0434\u043b\u044f WebRTC Opus &#8212; \u043a\u043e\u0440\u043e\u043b\u044c. Chrome \u0434\u0430\u0436\u0435 \u043d\u0435 \u0443\u043c\u0435\u0435\u0442 \u0434\u043e\u0433\u043e\u0432\u0430\u0440\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043e \u0447\u0451\u043c-\u0442\u043e \u0434\u0440\u0443\u0433\u043e\u043c \u043f\u0435\u0440\u0432\u044b\u043c.Asterisk \u0442\u043e\u0436\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 Opus (\u0447\u0435\u0440\u0435\u0437\u00a0allow=opus\u00a0\u0432\u00a0pjsip.conf), \u043f\u043b\u044e\u0441 PCMU \u0438 PCMA \u043a\u0430\u043a fallback. \u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0432\u044b\u0431\u043e\u0440\u0430 \u043a\u043e\u0434\u0435\u043a\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432\u043e \u0432\u0440\u0435\u043c\u044f\u00a0SDP-\u043e\u0431\u043c\u0435\u043d\u0430\u00a0(Session Description Protocol): \u043a\u0430\u0436\u0434\u0430\u044f \u0441\u0442\u043e\u0440\u043e\u043d\u0430 \u0437\u0430\u044f\u0432\u043b\u044f\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u043a\u043e\u0434\u0435\u043a\u043e\u0432 \u0441 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0430\u043c\u0438, \u0438 \u043e\u043d\u0438 \u043d\u0430\u0445\u043e\u0434\u044f\u0442 \u043f\u0435\u0440\u0435\u0441\u0435\u0447\u0435\u043d\u0438\u0435. \u0412\u043e\u0442 \u0442\u0438\u043f\u0438\u0447\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u0438\u0437 SDP:a=rtpmap:111 opus\/48000\/2a=fmtp:111 minptime=10;useinbandfec=1\u042d\u0442\u043e Opus \u0441 payload type 111, \u0447\u0430\u0441\u0442\u043e\u0442\u043e\u0439 \u0434\u0438\u0441\u043a\u0440\u0435\u0442\u0438\u0437\u0430\u0446\u0438\u0438 48 \u043a\u0413\u0446, \u0441\u0442\u0435\u0440\u0435\u043e, \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 ptime 10 \u043c\u0441 \u0438 \u0432\u043a\u043b\u044e\u0447\u0451\u043d\u043d\u0430\u044f \u0432\u043d\u0443\u0442\u0440\u0438\u043f\u043e\u043b\u043e\u0441\u043d\u0430\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0446\u0438\u044f \u043e\u0448\u0438\u0431\u043e\u043a.\u0417\u0432\u0443\u0447\u0438\u0442 \u0441\u0442\u0440\u043e\u0439\u043d\u043e. \u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c Call.\u0422\u0438\u0448\u0438\u043d\u0430.\u0413\u043b\u0430\u0432\u0430 2. \u041f\u0435\u0440\u0432\u044b\u0439 \u0437\u0432\u043e\u043d\u043e\u043a: \u00ab180 Ringing\u00bb \u0438 \u043c\u0451\u0440\u0442\u0432\u0430\u044f \u0442\u0438\u0448\u0438\u043d\u0430Asterisk \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 INVITE \u043e\u0442\u00a03001, \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u0435\u0433\u043e \u043f\u043e\u00a0dialplan\u00a0(extensions.conf) \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u043e\u0432\u044b\u0439 INVITE \u043a\u00a03002. \u0411\u0440\u0430\u0443\u0437\u0435\u0440\u00a03002\u00a0\u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0437\u0432\u043e\u043d\u043e\u043a, JsSIP \u0441\u0442\u0440\u0435\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u0435\u043c\u00a0newRTCSession. \u041d\u0430\u0448 \u043a\u043e\u0434 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u00a0session.answer(). Asterisk \u0432\u0438\u0434\u0438\u0442\u00a0180 Ringing.\u041d\u043e\u00a0200 OK\u00a0\u043d\u0435 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442.\u0414\u0432\u0430\u0434\u0446\u0430\u0442\u044c \u0441\u0435\u043a\u0443\u043d\u0434.\u00a0Nobody picked up in 20000 ms. Asterisk \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u00a0CANCEL, \u0438 \u0437\u0432\u043e\u043d\u043e\u043a \u0443\u043c\u0438\u0440\u0430\u0435\u0442.\u041f\u0435\u0440\u0432\u0430\u044f \u043c\u044b\u0441\u043b\u044c &#8212;\u00a0getUserMedia(). \u042d\u0442\u043e\u0442 \u0432\u044b\u0437\u043e\u0432 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u043c\u0438\u043a\u0440\u043e\u0444\u043e\u043d, \u0438 \u0435\u0441\u043b\u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0434\u0438\u0430\u043b\u043e\u0433 \u00ab\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c?\u00bb &#8212; \u043e\u043d \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442 \u0432\u0441\u0451. \u0420\u0435\u0448\u0435\u043d\u0438\u0435: \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u00a0ensureMic()\u00a0\u0434\u043e\u00a0\u0441\u0442\u0430\u0440\u0442\u0430 JsSIP UA, \u0447\u0442\u043e\u0431\u044b \u043a \u043c\u043e\u043c\u0435\u043d\u0442\u0443 \u0432\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u0437\u0432\u043e\u043d\u043a\u0430 \u043c\u0438\u043a\u0440\u043e\u0444\u043e\u043d \u0443\u0436\u0435 \u0431\u044b\u043b \u0433\u043e\u0442\u043e\u0432.\u041f\u043e\u043c\u043e\u0433\u043b\u043e? \u041d\u0435\u0442.\u00a0180 Ringing\u00a0\u0435\u0441\u0442\u044c,\u00a0200 OK\u00a0&#8212; \u043d\u0435\u0442.\u0413\u043b\u0430\u0432\u0430 3. ICE, \u0438\u043b\u0438 \u041f\u043e\u0447\u0435\u043c\u0443 \u0434\u0432\u0430 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0430 \u043d\u0435 \u043c\u043e\u0433\u0443\u0442 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442, \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u044c\u00a0ICE\u00a0&#8212; Interactive Connectivity Establishment. \u042d\u0442\u043e \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0430\u0431\u0431\u0440\u0435\u0432\u0438\u0430\u0442\u0443\u0440\u0430, \u044d\u0442\u043e \u0446\u0435\u043b\u044b\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0435\u0448\u0430\u0435\u0442 \u0444\u0443\u043d\u0434\u0430\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430: \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 \u0441\u0438\u0434\u044f\u0442 \u0437\u0430 NAT \u0438 \u043d\u0435 \u0437\u043d\u0430\u044e\u0442 \u0441\u0432\u043e\u0435\u0433\u043e \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e\u0433\u043e \u0430\u0434\u0440\u0435\u0441\u0430.ICE \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u0430\u043a:\u0411\u0440\u0430\u0443\u0437\u0435\u0440 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u00a0\u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u043e\u0432\u00a0&#8212; \u0430\u0434\u0440\u0435\u0441\u0430, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0434\u043e \u043d\u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0441\u0442\u0443\u0447\u0430\u0442\u044c\u0441\u044f:host\u00a0&#8212; \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0435 IP (192.168.x.x, 10.x.x.x)srflx\u00a0(server reflexive) &#8212; \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 IP, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0447\u0435\u0440\u0435\u0437 STUNrelay\u00a0&#8212; \u0430\u0434\u0440\u0435\u0441 \u043d\u0430 TURN-\u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0440\u0430\u0444\u0438\u043a\u041a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u044b \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432\u00a0SDP\u00a0(Session Description Protocol)\u041e\u0431\u0435 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u043f\u0440\u043e\u0432\u043e\u0434\u044f\u0442\u00a0connectivity checks\u00a0&#8212; \u043f\u0438\u043d\u0433\u0443\u044e\u0442 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u0430 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u0438\u043a\u0430\u041f\u043e\u0431\u0435\u0436\u0434\u0430\u0435\u0442 \u043f\u0430\u0440\u0430 \u0441 \u043b\u0443\u0447\u0448\u0435\u0439 \u0441\u0432\u044f\u0437\u043d\u043e\u0441\u0442\u044c\u044eSTUN\u00a0(Session Traversal Utilities for NAT) &#8212; \u043b\u0451\u0433\u043a\u0438\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b. \u0411\u0440\u0430\u0443\u0437\u0435\u0440 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 STUN-\u0441\u0435\u0440\u0432\u0435\u0440, \u0442\u043e\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442: \u00ab\u0422\u0432\u043e\u0439 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 IP &#8212; \u0442\u0430\u043a\u043e\u0439-\u0442\u043e, \u043f\u043e\u0440\u0442 &#8212; \u0442\u0430\u043a\u043e\u0439-\u0442\u043e\u00bb. \u042d\u0442\u043e \u043a\u0430\u043a \u0441\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u043f\u0440\u043e\u0445\u043e\u0436\u0435\u0433\u043e, \u043a\u0430\u043a \u0442\u044b \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0448\u044c \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b.TURN\u00a0(Traversal Using Relays around NAT) &#8212; \u0442\u044f\u0436\u0451\u043b\u0430\u044f \u0430\u0440\u0442\u0438\u043b\u043b\u0435\u0440\u0438\u044f. \u041a\u043e\u0433\u0434\u0430 \u043f\u0440\u044f\u043c\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e (symmetric NAT, \u0444\u0430\u0439\u0440\u0432\u043e\u043b), TURN-\u0441\u0435\u0440\u0432\u0435\u0440 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043f\u043e\u0441\u0440\u0435\u0434\u043d\u0438\u043a\u043e\u043c: \u0432\u0441\u0435 \u043c\u0435\u0434\u0438\u0430-\u043f\u0430\u043a\u0435\u0442\u044b \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0442 \u0447\u0435\u0440\u0435\u0437 \u043d\u0435\u0433\u043e. \u041c\u0435\u0434\u043b\u0435\u043d\u043d\u0435\u0435, \u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432\u0441\u0435\u0433\u0434\u0430.NAT-traversal \u043d\u0430 \u043f\u0430\u043b\u044c\u0446\u0430\u0445: (1) \u0437\u0430 NAT \u043d\u0435 \u0437\u043d\u0430\u0435\u0448\u044c \u0441\u0432\u043e\u0439 \u0430\u0434\u0440\u0435\u0441, (2) STUN \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u043a\u0430\u043a \u0442\u044b \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0448\u044c \u0441\u043d\u0430\u0440\u0443\u0436\u0438, (3) TURN \u043d\u043e\u0441\u0438\u0442 \u043f\u0430\u043a\u0435\u0442\u044b \u043c\u0435\u0436\u0434\u0443 \u0442\u0435\u043c\u0438, \u043a\u0442\u043e \u043d\u0435 \u0432\u0438\u0434\u0438\u0442 \u0434\u0440\u0443\u0433 \u0434\u0440\u0443\u0433\u0430\u041c\u044b \u043d\u0430\u0447\u0430\u043b\u0438 \u0431\u0435\u0437 STUN\/TURN:const PC_CONFIG = { iceServers: [] };\u0411\u0440\u0430\u0443\u0437\u0435\u0440\u00a03002\u00a0\u0441\u043e\u0431\u0440\u0430\u043b \u0442\u043e\u043b\u044c\u043a\u043e\u00a0host-\u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u043e\u0432:\u00a0192.168.1.98,\u00a010.8.0.10\u00a0(VPN),\u00a0fdbc:8196:&#8230;\u00a0(IPv6 link-local). \u0412\u0441\u0435 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0435. Asterisk, \u0441\u0438\u0434\u044f\u0449\u0438\u0439 \u043d\u0430 VPS, \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0434\u043e \u043d\u0438\u0445 \u0434\u043e\u0441\u0442\u0443\u0447\u0430\u0442\u044c\u0441\u044f. ICE \u2192\u00a0failed. \u0417\u0432\u043e\u043d\u043e\u043a \u2192 \u0442\u0438\u0448\u0438\u043d\u0430.\u0413\u043b\u0430\u0432\u0430 4. Google STUN &#8212; \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u041f\u0435\u0440\u0432\u044b\u0439 \u0440\u0435\u0444\u043b\u0435\u043a\u0441: \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0435 STUN-\u0441\u0435\u0440\u0432\u0435\u0440\u044b Google.iceServers: [  { urls: &#171;stun:stun.l.google.com:19302&#187; },  { urls: &#171;stun:stun1.l.google.com:19302&#187; }]\u0417\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e? \u041d\u0435\u0442.\u00a0stun.l.google.com\u00a0\u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d \u0432 \u0441\u0435\u0442\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0411\u0440\u0430\u0443\u0437\u0435\u0440 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u00a0srflx-\u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u0430, ICE \u0441\u043d\u043e\u0432\u0430 \u043d\u0430\u0448\u0451\u043b \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0435 \u0430\u0434\u0440\u0435\u0441\u0430.\u0413\u043b\u0430\u0432\u0430 5. \u041f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u043c \u0441\u0432\u043e\u0439 Coturn\u0415\u0441\u043b\u0438 Google STUN \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d &#8212; \u043f\u043e\u0434\u043d\u0438\u043c\u0435\u043c \u0441\u0432\u043e\u0439. \u041d\u0430 \u0442\u043e\u043c \u0436\u0435 VPS, \u0433\u0434\u0435 \u0436\u0438\u0432\u0451\u0442 Asterisk:docker run -d &#8212;name coturn &#8212;network host coturn\/coturn \\  -n &#8212;log-file=stdout \\  &#8212;listening-ip=0.0.0.0 \\  &#8212;external-ip=203.0.113.10 \\  &#8212;min-port=49152 &#8212;max-port=49252 \\  &#8212;lt-cred-mech &#8212;realm=voip.local &#8212;fingerprint \\  &#8212;user webrtc:S3cr3t_turn\u041a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b:&#8212;network host\u00a0&#8212; \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0441\u0435\u0442\u044c \u0445\u043e\u0441\u0442\u0430 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e, \u0431\u0435\u0437 Docker NAT&#8212;external-ip\u00a0&#8212; Coturn \u0437\u043d\u0430\u0435\u0442 \u0441\u0432\u043e\u0439 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 IP \u0434\u043b\u044f relay-\u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u043e\u0432&#8212;lt-cred-mech\u00a0&#8212; Long-Term Credential Mechanism (RFC 5389), \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0434\u043b\u044f TURN&#8212;min-port\/&#8212;max-port\u00a0&#8212; \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d \u043f\u043e\u0440\u0442\u043e\u0432 \u0434\u043b\u044f relay-\u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0439\u0422\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0441\u0432\u043e\u0439 STUN+TURN \u043d\u0430\u00a0203.0.113.10:3478. \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u043a\u043e\u043d\u0444\u0438\u0433 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432:iceServers: [  { urls: &#171;stun:203.0.113.10:3478&#187; },  {    urls: &#171;turn:203.0.113.10:3478?transport=udp&#187;,    username: &#171;webrtc&#187;,    credential: &#171;S3cr3t_turn&#187;  }]\u0413\u043b\u0430\u0432\u0430 6. \u041b\u043e\u0432\u0443\u0448\u043a\u0430 TCP TURN \u0438 \u043e\u0448\u0438\u0431\u043a\u0430 701\u0417\u0432\u043e\u043d\u0438\u043c. ICE gathering \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f&#8230; \u0438 \u0437\u0430\u0432\u0438\u0441\u0430\u0435\u0442. \u0412 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 Chrome:ice-candidate-error: url=turn:203.0.113.10:3478?transport=tcp code=701  text=Address not associated with the desired network interface.\u041c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 TCP TURN \u043d\u0430\u0440\u044f\u0434\u0443 \u0441 UDP. Chrome \u0447\u0435\u0441\u0442\u043d\u043e \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0430\u043b\u043b\u043e\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c relay \u0447\u0435\u0440\u0435\u0437 TCP &#8212; \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0443 701. \u041d\u043e \u0432\u043e\u0442 \u043f\u043e\u0434\u0432\u043e\u0445:\u00a0Chrome \u043d\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u0442 ICE gathering, \u043f\u043e\u043a\u0430 \u043d\u0435 \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 TCP TURN. \u0412\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 \u0442\u0430\u0439\u043c\u0430\u0443\u0442 &#8212; \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u0441\u0435\u043a\u0443\u043d\u0434.\u0410 JsSIP \u0436\u0434\u0451\u0442\u00a0iceGatheringState === &#171;complete&#187;, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0432\u0441\u0435 \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u044b \u0432 SDP \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e. \u041f\u043e\u043a\u0430 gathering \u043d\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d &#8212; SDP \u043d\u0435 \u0443\u0445\u043e\u0434\u0438\u0442,\u00a0200 OK\u00a0\u043d\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f, Asterisk \u0441\u0447\u0438\u0442\u0430\u0435\u0442 \u0434\u043e 20 \u0438 \u0432\u0435\u0448\u0430\u0435\u0442 \u0442\u0440\u0443\u0431\u043a\u0443.\u0420\u0435\u0448\u0435\u043d\u0438\u0435: \u0443\u0431\u0440\u0430\u0442\u044c TCP TURN, \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e UDP.urls: &#171;turn:203.0.113.10:3478?transport=udp&#187;\u0413\u043b\u0430\u0432\u0430 7.\u00a0event.ready()\u00a0&#8212; 40 \u0441\u0435\u043a\u0443\u043d\u0434 \u0432\u043f\u0443\u0441\u0442\u0443\u044eTCP TURN \u0443\u0431\u0440\u0430\u043d. \u0417\u0432\u043e\u043d\u0438\u043c. ICE gathering&#8230; \u0432\u0441\u0451 \u0435\u0449\u0451 \u0432\u0438\u0441\u0438\u0442. Relay-\u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442 \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0437\u0430 \u0441\u0435\u043a\u0443\u043d\u0434\u0443, \u043d\u043e SDP \u0443\u0445\u043e\u0434\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0435\u0440\u0435\u0437\u00a040 \u0441\u0435\u043a\u0443\u043d\u0434.\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0442\u0430\u0439\u043c\u043b\u0430\u0439\u043d \u0432 \u043b\u043e\u0433:23:01:43\u00a0&#8212; relay-\u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442 \u0441\u043e\u0431\u0440\u0430\u043d23:02:23\u00a0&#8212; SDP \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d40 \u0441\u0435\u043a\u0443\u043d\u0434 \u0440\u0430\u0437\u043d\u0438\u0446\u044b. \u0413\u0434\u0435 \u043e\u043d\u0438 \u0442\u0435\u0440\u044f\u044e\u0442\u0441\u044f?\u041e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u0432 JsSIP \u0435\u0441\u0442\u044c \u0445\u0438\u0442\u0440\u043e\u0441\u0442\u044c. \u0421\u043e\u0431\u044b\u0442\u0438\u0435\u00a0icecandidate\u00a0\u043d\u0430\u00a0\u0441\u0435\u0441\u0441\u0438\u0438\u00a0(\u043d\u0435 \u043d\u0430 RTCPeerConnection!) \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u043c\u0435\u0442\u043e\u0434\u043e\u043c\u00a0event.ready(). \u0415\u0441\u043b\u0438 \u0432\u044b \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043b\u0438\u0441\u044c \u043d\u0430 \u044d\u0442\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0438\u00a0\u043d\u0435 \u0432\u044b\u0437\u0432\u0430\u043b\u0438\u00a0ready()\u00a0&#8212; JsSIP \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u0443\u0435\u0442 \u044d\u0442\u043e \u043a\u0430\u043a \u00ab\u043f\u043e\u0434\u043e\u0436\u0434\u0438, \u044f \u0435\u0449\u0451 \u0434\u0443\u043c\u0430\u044e\u00bb. \u0418 \u0436\u0434\u0451\u0442. \u0421\u0432\u043e\u0439 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 \u0442\u0430\u0439\u043c\u0430\u0443\u0442 &#8212; ~40 \u0441\u0435\u043a\u0443\u043d\u0434.\u041d\u0430\u0448 \u043a\u043e\u0434:session.on(&#171;icecandidate&#187;, (ev) =&gt; {  log(&#171;ICE candidate generated&#187;);  \/\/ \u0417\u0430\u0431\u044b\u043b\u0438 ev.ready()!});\u041c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u0430 \u0438 \u043d\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u043b\u0438 JsSIP, \u0447\u0442\u043e \u043e\u043d \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442\u044c. \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0442\u0435\u0440\u043f\u0435\u043b\u0438\u0432\u043e \u0436\u0434\u0430\u043b\u0430 40 \u0441\u0435\u043a\u0443\u043d\u0434, \u043f\u043e\u0442\u043e\u043c \u0441\u0434\u0430\u0432\u0430\u043b\u0430\u0441\u044c \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u043b\u0430 SDP.JsSIP \u0442\u0435\u0440\u043f\u0435\u043b\u0438\u0432\u043e \u0436\u0434\u0451\u0442, \u043f\u043e\u043a\u0430 \u043a\u0442\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u0432\u044b\u0437\u043e\u0432\u0435\u0442 ready()\u0418\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 &#8212; \u043e\u0434\u043d\u0430 \u0441\u0442\u0440\u043e\u043a\u0430:session.on(&#171;icecandidate&#187;, (ev) =&gt; {  log(&#171;ICE candidate generated&#187;);  if (ev &amp;&amp; typeof ev.ready === &#171;function&#187;) ev.ready();});\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e INVITE \u0438\u00a0200 OK\u00a0\u0441\u0442\u0430\u043b\u0438 \u0443\u043b\u0435\u0442\u0430\u0442\u044c \u0437\u0430 1\u20132 \u0441\u0435\u043a\u0443\u043d\u0434\u044b.\u0413\u043b\u0430\u0432\u0430 8.\u00a0ice_host_candidates\u00a0&#8212; \u0441\u0435\u043a\u0446\u0438\u044f, \u0430 \u043d\u0435 \u043a\u043b\u044e\u0447\u0417\u0432\u043e\u043d\u043e\u043a \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f!\u00a0session accepted,\u00a0session confirmed. \u041d\u043e\u00a0out_packets=0. \u0422\u0438\u0448\u0438\u043d\u0430 \u0432 \u044d\u0444\u0438\u0440\u0435.\u0421\u043c\u043e\u0442\u0440\u0438\u043c SDP, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 Asterisk \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0443\u00a03002:c=IN IP4 192.168.0.129a=candidate:Hc0a80081 1 UDP 2130706431 192.168.0.129 18008 typ hosta=candidate:Hac110001 1 UDP 2130706431 172.17.0.1 18008 typ host192.168.0.129\u00a0&#8212; \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0439 IP VPS (\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u00a0ens3).\u00a0172.17.0.1\u00a0&#8212; Docker bridge. \u041e\u0431\u0430 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0438\u0437 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430. \u0411\u0440\u0430\u0443\u0437\u0435\u0440 \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c RTP \u043d\u0430 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0435 \u0430\u0434\u0440\u0435\u0441\u0430 &#8212; \u0438, \u0440\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u043e\u0445\u043e\u0434\u0438\u0442.\u0412\u00a0rtp.conf\u00a0\u0443 \u043d\u0430\u0441 \u0431\u044b\u043b\u043e:[general]ice_host_candidate=203.0.113.10\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e. \u0427\u0438\u0442\u0430\u0435\u043c\u00a0\u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439\u00a0rtp.conf.sample\u00a0\u0438\u0437 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f Asterisk \u0438 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0435\u043c:\u00a0ice_host_candidates\u00a0&#8212; \u044d\u0442\u043e\u00a0\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0441\u0435\u043a\u0446\u0438\u044f, \u0430 \u043d\u0435 \u043a\u043b\u044e\u0447 \u0432\u00a0[general]. \u0418 \u0444\u043e\u0440\u043c\u0430\u0442 \u043c\u0430\u043f\u043f\u0438\u043d\u0433\u0430:[ice_host_candidates]192.168.0.129 =&gt; 203.0.113.10\u042d\u0442\u043e \u0433\u043e\u0432\u043e\u0440\u0438\u0442 Asterisk: \u00ab\u041a\u043e\u0433\u0434\u0430 \u0442\u044b \u0432\u0438\u0434\u0438\u0448\u044c \u0441\u0432\u043e\u0439 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0430\u0434\u0440\u0435\u0441\u00a0192.168.0.129\u00a0\u0432 ICE-\u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u0430\u0445 &#8212; \u0437\u0430\u043c\u0435\u043d\u0438 \u0435\u0433\u043e \u043d\u0430 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439\u00a0203.0.113.10\u00bb.\u041f\u043e\u0441\u043b\u0435 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f SDP \u0441\u0442\u0430\u043b \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u043c:a=candidate:H59684ac5 1 UDP 2130706431 203.0.113.10 18008 typ host\u0413\u043b\u0430\u0432\u0430 9.\u00a0relay-only\u00a0\u0438 \u043f\u0435\u0442\u043b\u044f 403\u041a \u044d\u0442\u043e\u043c\u0443 \u043c\u043e\u043c\u0435\u043d\u0442\u0443 \u043c\u044b \u0443\u0436\u0435 \u0443\u0441\u0442\u0430\u043b\u0438 \u043e\u0442 \u0434\u043e\u043b\u0433\u043e\u0433\u043e ICE gathering (Chrome \u043f\u0435\u0440\u0435\u0431\u0438\u0440\u0430\u043b host, srflx, relay \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u044b \u043f\u043e \u0432\u0441\u0435\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430\u043c &#8212; WiFi, VPN, IPv6). \u0420\u0435\u0448\u0435\u043d\u0438\u0435:\u00a0iceTransportPolicy: &#171;relay&#187;\u00a0&#8212; \u0444\u043e\u0440\u0441\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u00a0\u0442\u043e\u043b\u044c\u043a\u043e\u00a0TURN relay.const PC_CONFIG = {  iceTransportPolicy: &#171;relay&#187;,  iceServers: [{ urls: &#171;turn:203.0.113.10:3478?transport=udp&#187;, &#8230; }]};ICE gathering \u0441\u0442\u0430\u043b \u043c\u043e\u043b\u043d\u0438\u0435\u043d\u043e\u0441\u043d\u044b\u043c: \u043e\u0434\u0438\u043d relay-\u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442, \u0433\u043e\u0442\u043e\u0432\u043e. \u0417\u0432\u043e\u043d\u043e\u043a \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0437\u0430 \u0441\u0435\u043a\u0443\u043d\u0434\u044b. \u0418\u0434\u0435\u0430\u043b\u044c\u043d\u043e?\u041d\u0435\u0442.\u00a0out_packets=0. \u041e\u043f\u044f\u0442\u044c.\u0412\u043a\u043b\u044e\u0447\u0430\u0435\u043c RTP debug \u043d\u0430 Asterisk \u0438 \u0432\u0438\u0434\u0438\u043c \u0432 \u043b\u043e\u0433\u0430\u0445:pjproject: CreatePermission failed for IP 203.0.113.10: 403\/Forbidden IP\u0427\u0442\u043e \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e: \u043c\u044b \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438\u00a0turnaddr=127.0.0.1:3478\u00a0\u0432\u00a0rtp.conf\u00a0Asterisk, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u0442\u043e\u0436\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u043b relay-\u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u044b. Asterisk \u0430\u043b\u043b\u043e\u0446\u0438\u0440\u043e\u0432\u0430\u043b relay \u043d\u0430 Coturn (\u0430\u0434\u0440\u0435\u0441\u00a0203.0.113.10:49160). \u0411\u0440\u0430\u0443\u0437\u0435\u0440 \u0442\u043e\u0436\u0435 \u0430\u043b\u043b\u043e\u0446\u0438\u0440\u043e\u0432\u0430\u043b relay \u043d\u0430 \u0442\u043e\u043c \u0436\u0435 Coturn (203.0.113.10:49202).\u0422\u0435\u043f\u0435\u0440\u044c Asterisk \u0447\u0435\u0440\u0435\u0437 \u0441\u0432\u043e\u0439 TURN relay \u0445\u043e\u0447\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043f\u0430\u043a\u0435\u0442 \u043d\u0430\u00a0203.0.113.10:49202\u00a0(relay \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430). \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043e\u043d \u043f\u0440\u043e\u0441\u0438\u0442 Coturn: \u00ab\u0421\u043e\u0437\u0434\u0430\u0439 permission \u043d\u0430 IP\u00a0203.0.113.10\u00bb. Coturn \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442:\u00a0403 Forbidden. \u041f\u043e\u0447\u0435\u043c\u0443? \u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e\u00a0203.0.113.10\u00a0&#8212; \u044d\u0442\u043e\u00a0\u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 IP Coturn. TURN-\u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0430\u0435\u0442 relay-\u0438\u0442\u044c \u0442\u0440\u0430\u0444\u0438\u043a \u0441\u0430\u043c\u043e\u043c\u0443 \u0441\u0435\u0431\u0435 &#8212; \u044d\u0442\u043e \u0437\u0430\u0449\u0438\u0442\u0430 \u043e\u0442 \u043f\u0435\u0442\u0435\u043b\u044c.\u041c\u044b \u043f\u043e\u043f\u0430\u043b\u0438 \u0432 \u043b\u043e\u0432\u0443\u0448\u043a\u0443: \u043e\u0431\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 (Asterisk \u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440) \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 TURN-\u0441\u0435\u0440\u0432\u0435\u0440, \u0438 \u0438\u0445&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-495489","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/495489","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=495489"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/495489\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=495489"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=495489"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=495489"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}