{"id":480781,"date":"2026-05-23T21:04:56","date_gmt":"2026-05-23T21:04:56","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=480781"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=480781","title":{"rendered":"RustDesk Pro \u0432 \u0420\u043e\u0441\u0441\u0438\u0438 \u043d\u0435 \u043a\u0443\u043f\u0438\u0442\u044c. \u041f\u043e\u0441\u043b\u0435 \u0434\u043e\u043b\u0433\u0438\u0445 \u043b\u0435\u0442 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u044b \u0441\u043e\u0431\u0440\u0430\u043b\u0438 \u0441\u0432\u043e\u0451 \u0447\u0435\u0441\u0442\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<blockquote>\n<p><em>\u0421\u0442\u0430\u0442\u044c\u044f \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0435\u0441\u044f\u0442\u044c \u043b\u0435\u0442 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043b \u0447\u0443\u0436\u0438\u0435 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u044b, \u0430 \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u0435\u043b\u0430\u0435\u0442 \u0442\u043e, \u0447\u0435\u043c \u0445\u043e\u0447\u0435\u0442 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0430\u043c.<\/em><\/p>\n<\/blockquote>\n<p><em>\u0411\u0435\u0440\u0435\u043c \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439\u00a0<\/em><a href=\"https:\/\/github.com\/rustdesk\/rustdesk\" rel=\"noopener noreferrer nofollow\"><em>RustDesk<\/em><\/a><em>\u00a0(AGPLv3), \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u043c \u0444\u043e\u0440\u043a, \u043f\u0430\u0442\u0447\u0438\u043c \u0435\u0433\u043e \u043d\u0430 \u043b\u0435\u0442\u0443 \u0432 GitHub Actions \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430. \u041f\u043e\u0432\u0435\u0440\u0445 &#8212; \u0440\u043e\u0441\u0441\u0438\u0439\u0441\u043a\u0430\u044f \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430: \u0441\u0435\u0440\u0432\u0435\u0440\u044b \u0432 \u0420\u0424, \u043e\u043f\u043b\u0430\u0442\u0430 \u043f\u043e \u0441\u0447\u0451\u0442\u0443 \u044e\u0440.\u043b\u0438\u0446\u0430\u043c, \u043a\u043e\u0440\u043f\u043e\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0439 SSO \u0447\u0435\u0440\u0435\u0437 Active Directory \u0438 \u042f\u043d\u0434\u0435\u043a\u0441 ID, \u0437\u0430\u0449\u0438\u0442\u0430 \u043e\u0442 \u043c\u043e\u0448\u0435\u043d\u043d\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043d\u0430 Android.<\/em><\/p>\n<p>\u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0410\u0440\u0442\u0443\u0440 \u0412\u0430\u043b\u0438\u0435\u0432. \u042f \u0434\u0435\u043b\u0430\u044e \u043d\u0435 \u00ab\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0438\u043c\u043f\u043e\u0440\u0442\u043e\u0437\u0430\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u0441 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0435\u0439 \u0424\u0421\u0422\u042d\u041a\u00bb \u0440\u0430\u0434\u0438 \u0437\u0430\u043a\u0443\u043f\u043e\u043a. \u041f\u0440\u043e\u0441\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 \u043f\u0440\u043e\u0434\u0443\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u0431\u044b \u0441\u0430\u043c \u0445\u043e\u0442\u0435\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0435\u0441\u044f\u0442\u044c \u043b\u0435\u0442 \u043d\u0430\u0437\u0430\u0434, \u043a\u043e\u0433\u0434\u0430 \u0441\u0438\u0434\u0435\u043b \u043d\u0430 \u0441\u0430\u043f\u043f\u043e\u0440\u0442\u0435 \u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432.<\/p>\n<h3>\u041f\u043e\u0447\u0435\u043c\u0443 \u044f \u0432\u043e\u043e\u0431\u0449\u0435 \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u044e<\/h3>\n<p>\u0414\u0435\u0441\u044f\u0442\u044c \u043b\u0435\u0442 \u044f \u0431\u044b\u043b \u044d\u043d\u0438\u043a\u0435\u0439\u0449\u0438\u043a\u043e\u043c, \u043f\u043e\u0442\u043e\u043c \u0441\u0438\u0441\u0430\u0434\u043c\u0438\u043d\u043e\u043c, \u043f\u043e\u0442\u043e\u043c \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043e\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0432 IT-\u0430\u0443\u0442\u0441\u043e\u0440\u0441\u0435. \u041f\u0440\u043e\u0448\u0451\u043b TeamViewer, AnyDesk, LiteManager, AeroAdmin, Ammyy, \u0432\u0441\u0451 \u0447\u0442\u043e \u0432\u044b \u0432\u0438\u0434\u0438\u0442\u0435 \u0432\u00a0\u0441\u043f\u0438\u0441\u043a\u0435. \u0423 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u0432\u043e\u0438 \u0442\u0430\u0440\u0430\u043a\u0430\u043d\u044b:<\/p>\n<ul>\n<li>\n<p><strong>AnyDesk <\/strong>\u0441\u0447\u0438\u0442\u0430\u0435\u0442 \u0432\u0430\u0441 \u043a\u043e\u043c\u043c\u0435\u0440\u0447\u0435\u0441\u043a\u0438\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c, \u0435\u0441\u043b\u0438 \u0432\u044b \u043f\u043e\u043c\u043e\u0433\u043b\u0438 \u043c\u0430\u043c\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u0440\u0438\u043d\u0442\u0435\u0440 \u0434\u0432\u0430\u0436\u0434\u044b<\/p>\n<\/li>\n<li>\n<p><strong>LiteManager<\/strong>\u00a0&#8212; \u043f\u044b\u0442\u0430\u043b\u0438\u0441\u044c, \u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0438\u0437 2008 \u0433\u043e\u0434\u0430 \u043f\u043b\u044e\u0441 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u044f \u043f\u043e \u0448\u0442\u0443\u043a\u0430\u043c, \u043d\u0435\u0443\u0434\u043e\u0431\u043d\u043e<\/p>\n<\/li>\n<li>\n<p><strong>RuDesktop<\/strong>\u00a0&#8212; \u043f\u0440\u043e \u043d\u0438\u0445 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u043d\u0438\u0436\u0435<\/p>\n<\/li>\n<\/ul>\n<h3>\u041f\u0440\u043e \u0447\u0435\u0441\u0442\u043d\u043e\u0441\u0442\u044c \u0441 AGPLv3 (\u0438 \u043f\u043e\u0447\u0435\u043c\u0443 \u044f \u043d\u0435 \u00ab\u043a\u0430\u043a RuDesktop\u00bb)<\/h3>\n<p>\u041a\u043e\u0433\u0434\u0430 \u044f \u043d\u0430\u0447\u0430\u043b, \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u043b \u0440\u043e\u0441\u0441\u0438\u0439\u0441\u043a\u0438\u0445 \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u043e\u0432. \u041e\u0434\u0438\u043d \u0438\u0437 \u0437\u0430\u043c\u0435\u0442\u043d\u044b\u0445 &#8212; RuDesktop. \u0423 \u043d\u0438\u0445 \u043d\u0430 \u0441\u0430\u0439\u0442\u0435 \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0435 \u0431\u0435\u0439\u0434\u0436\u0438 \u00ab\u0420\u0435\u0435\u0441\u0442\u0440 \u0440\u043e\u0441\u041f\u041e\u00bb, \u00ab\u0421\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0424\u0421\u0422\u042d\u041a\u00bb, \u0438 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0435 \u0437\u0430\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e &#171;\u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443&#187;. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c &#8212; \u044d\u0442\u043e \u0444\u043e\u0440\u043a RustDesk \u0431\u0435\u0437 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u043e\u0432, \u0447\u0442\u043e\u00a0<strong>\u043f\u0440\u044f\u043c\u043e \u043d\u0430\u0440\u0443\u0448\u0430\u0435\u0442 AGPLv3<\/strong>.<\/p>\n<p>AGPL &#8212; \u044d\u0442\u043e \u043d\u0435 \u00ab\u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0438 \u0437\u0430\u0431\u044b\u0442\u044c\u00bb. \u042d\u0442\u043e: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0448\u044c &#8212; \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0439 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f. \u0420\u0430\u0437\u0434\u0430\u0451\u0448\u044c \u043a\u0430\u043a \u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 &#8212; \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0439. \u041b\u044e\u0431\u043e\u0439 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438, \u0435\u0441\u043b\u0438 \u0443\u0437\u043d\u0430\u0435\u0442 \u043f\u0440\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435.<\/p>\n<blockquote>\n<p>\u042f \u043d\u0435 \u0445\u043e\u0447\u0443 \u0442\u0430\u043a. \u042d\u0442\u043e \u043a\u0440\u0430\u0442\u043a\u043e\u0441\u0440\u043e\u0447\u043d\u043e \u0432\u044b\u0433\u043e\u0434\u043d\u043e (\u043d\u0438\u043a\u0442\u043e \u043d\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442 \u043f\u0440\u0438 \u0442\u0435\u043d\u0434\u0435\u0440\u0435), \u043d\u043e \u0434\u043e\u043b\u0433\u043e\u0441\u0440\u043e\u0447\u043d\u043e &#8212; \u0442\u0438\u043a\u0430\u044e\u0449\u0430\u044f \u0431\u043e\u043c\u0431\u0430. \u041a\u043e\u0433\u0434\u0430 RustDesk \u043f\u0440\u043e\u0441\u043d\u0451\u0442\u0441\u044f \u0438 \u043f\u043e\u0434\u0430\u0441\u0442 \u0432 \u0441\u0443\u0434 &#8212; \u0432\u0441\u0435 \u044d\u0442\u0438 \u0431\u0435\u0439\u0434\u0436\u0438 \u0438\u0441\u043f\u0430\u0440\u044f\u0442\u0441\u044f.<\/p>\n<\/blockquote>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0432\u044b\u0431\u0440\u0430\u043b\u00a0<strong>\u043f\u043e\u0434\u0445\u043e\u0434 \u00ab\u043d\u0435 \u0444\u043e\u0440\u043a\u00bb<\/strong>. \u041e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u0435 \u043d\u0438\u0436\u0435.<\/p>\n<h3>\u0413\u043b\u0430\u0432\u043d\u0430\u044f \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0438\u0434\u0435\u044f: \u043f\u0430\u0442\u0447\u0438\u043c upstream \u043d\u0430 \u043b\u0435\u0442\u0443<\/h3>\n<p>\u041e\u0431\u044b\u0447\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430 when \u0442\u044b \u0434\u0435\u043b\u0430\u0435\u0448\u044c \u043f\u0440\u043e\u0434\u0443\u043a\u0442 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 open-source:<\/p>\n<ol>\n<li>\n<p>\u0424\u043e\u0440\u043a\u0430\u0435\u0448\u044c \u0440\u0435\u043f\u043e<\/p>\n<\/li>\n<li>\n<p>\u041c\u0435\u043d\u044f\u0435\u0448\u044c \u043d\u0443\u0436\u043d\u043e\u0435 \u043f\u0440\u044f\u043c\u043e \u0432 \u043a\u043e\u0434\u0435<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0448\u044c fork \u0432\u0435\u0447\u043d\u043e: \u043a\u0430\u0436\u0434\u043e\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 upstream&#8217;\u0430 \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u043c\u0435\u0440\u0436\u0438\u0448\u044c \u0438 \u0440\u0435\u0448\u0430\u0435\u0448\u044c \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u044b<\/p>\n<\/li>\n<\/ol>\n<p>\u042d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043d\u043e \u0447\u0435\u0440\u0435\u0437 \u0433\u043e\u0434 upstream \u0443\u0439\u0434\u0451\u0442 \u0434\u0430\u043b\u0435\u043a\u043e, \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0444\u043e\u0440\u043a \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0431\u043e\u043b\u044c\u043d\u043e. \u0423 RustDesk \u043a\u043e\u043c\u043c\u0438\u0442\u044b \u043f\u0440\u0438\u043b\u0435\u0442\u0430\u044e\u0442 \u043a\u0430\u0436\u0434\u044b\u0439 \u0434\u0435\u043d\u044c.<\/p>\n<p><strong>\u042f \u0434\u0435\u043b\u0430\u044e \u0438\u043d\u0430\u0447\u0435.<\/strong>\u00a0\u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0441 workflow-\u0441\u0431\u043e\u0440\u043a\u0430\u043c\u0438 \u043f\u0440\u043e\u0441\u0442\u043e\u00a0<strong>\u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u0442 upstream \u0438 \u043f\u0430\u0442\u0447\u0438\u0442 sed-\u043e\u043c<\/strong>\u00a0\u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u0441\u0431\u043e\u0440\u043a\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430:<\/p>\n<pre><code>- name: Checkout RustDesk source (master)  uses: actions\/checkout@v4  with:    repository: rustdesk\/rustdesk    ref: master    submodules: recursive- name: Aggressive rebrand  if: ${{ inputs.rebrand_strings == 'true' }}  run: |    find .\/flutter\/lib -name \"*.dart\" -type f \\      -exec sed -i \"s|RustDesk|${APP_NAME}|g\" {} +    sed -i \"s|hbb_common::config::APP_NAME.read().unwrap().clone()|\\\"${APP_NAME}\\\".to_string()|g\" \\      .\/src\/common.rs    sed -i \"s|android:scheme=\\\"rustdesk\\\"|android:scheme=\\\"${BRAND_LOWER}\\\"|g\" \\      .\/flutter\/android\/app\/src\/main\/AndroidManifest.xml<\/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>\u041a\u0430\u0436\u0434\u0430\u044f \u0441\u0431\u043e\u0440\u043a\u0430 \u0442\u044f\u043d\u0435\u0442 \u0441\u0432\u0435\u0436\u0438\u0439 upstream (\u0438\u043b\u0438 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u0442\u0435\u0433, \u043a\u0430\u043a\u043e\u0439 \u043a\u043b\u0438\u0435\u043d\u0442 \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u043b), \u043d\u0430\u043a\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043c\u043e\u0438 \u043f\u0430\u0442\u0447\u0438, \u0431\u0438\u043b\u0434\u0438\u0442, \u0443\u0434\u0430\u043b\u044f\u0435\u0442. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 &#8212;\u00a0<code>.exe<\/code>,\u00a0<code>.apk<\/code>,\u00a0<code>.dmg<\/code>,\u00a0<code>.deb<\/code>\u00a0\u043f\u043e\u0434 \u043a\u043b\u0438\u0435\u043d\u0442\u0430.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/dc3\/2f4\/51d\/dc32f451ddfb0a03a93a639f970fe604.png\" alt=\"\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\" title=\"\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\" width=\"1007\" height=\"868\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/dc3\/2f4\/51d\/dc32f451ddfb0a03a93a639f970fe604.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/dc3\/2f4\/51d\/dc32f451ddfb0a03a93a639f970fe604.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430<\/figcaption><\/div>\n<\/figure>\n<h4>\u0427\u0442\u043e \u044d\u0442\u043e \u0434\u0430\u0451\u0442<\/h4>\n<ul>\n<li>\n<p><strong>\u042f \u043d\u0435 \u043e\u0431\u044f\u0437\u0430\u043d \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u0444\u043e\u0440\u043a<\/strong>\u00a0&#8212; \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0444\u043e\u0440\u043a\u0430 \u043d\u0435\u0442. \u0415\u0441\u0442\u044c downstream-\u043f\u0430\u0442\u0447\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0435 (\u0432 \u043c\u043e\u0451\u043c workflow-\u0440\u0435\u043f\u043e) \u0438 AGPL-\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0435.<\/p>\n<\/li>\n<li>\n<p><strong>Upstream \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f<\/strong>\u00a0&#8212; \u0437\u0430\u0445\u043e\u0442\u0435\u043b \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0441 RustDesk 1.4.5? \u0423\u043a\u0430\u0437\u0430\u043b\u00a0<code>version: 1.4.5<\/code>\u00a0&#8212; workflow \u0441\u0430\u043c \u043f\u043e\u0434\u0442\u044f\u043d\u0435\u0442.<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u0430\u0436\u0434\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0410 &#8212; \u044d\u0442\u043e \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u0430\u044f \u0441\u0431\u043e\u0440\u043a\u0430<\/strong>\u00a0\u0441\u043e \u0441\u0432\u043e\u0438\u043c \u0431\u0440\u0435\u043d\u0434\u043e\u043c, \u0441\u0432\u043e\u0438\u043c \u0437\u0430\u0448\u0438\u0442\u044b\u043c tenant slug, \u0441\u0432\u043e\u0438\u043c \u043d\u0430\u0431\u043e\u0440\u043e\u043c \u0444\u0438\u0447\u0435\u0439.<\/p>\n<\/li>\n<\/ul>\n<h4>\u041a\u0430\u043a\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b<\/h4>\n<p>\u0413\u043b\u0430\u0432\u043d\u0430\u044f &#8212;\u00a0<strong>upstream \u043b\u043e\u043c\u0430\u0435\u0442 \u0438\u043c\u0435\u043d\u0430<\/strong>. \u042f \u043e\u0434\u043d\u0430\u0436\u0434\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043b sed-\u043f\u0430\u0442\u0447 \u043f\u043e\u0434 \u0430\u043d\u043a\u0435\u0440\u00a0<code>PopupMenuButton&lt;String&gt;<\/code>, \u0430 upstream \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043b \u0432\u0438\u0434\u0436\u0435\u0442 \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u0440\u0435\u043b\u0438\u0437\u0435. Sed \u043c\u043e\u043b\u0447\u0430 \u043d\u0435 \u043d\u0430\u0448\u0451\u043b \u043f\u0430\u0442\u0442\u0435\u0440\u043d (<code>continue-on-error: true<\/code>), \u0441\u0431\u043e\u0440\u043a\u0430 \u043f\u0440\u043e\u0448\u043b\u0430, \u043d\u043e\u00a0<strong>\u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043d\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0441\u044f<\/strong>. \u041e\u0442\u043a\u0440\u044b\u043b \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442 &#8212; \u043d\u0435\u0442 \u043a\u043d\u043e\u043f\u043a\u0438 \u00ab\u0417\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u043f\u043e\u043c\u043e\u0449\u044c\u00bb. \u0414\u043e\u043b\u0433\u043e \u0438\u0441\u043a\u0430\u043b \u043f\u043e\u0447\u0435\u043c\u0443.<\/p>\n<p>\u0420\u0435\u0448\u0435\u043d\u0438\u0435: \u043f\u0438\u0441\u0430\u0442\u044c\u00a0<strong>defensive multi-anchor patches<\/strong>\u00a0\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0447\u0442\u043e \u043f\u0430\u0442\u0447 \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043b\u0441\u044f:<\/p>\n<pre><code>sed -i \"s|buildTip(context),|buildTip(context),\\n  Padding(...)|\" desktop_home_page.dartecho \"Verification:\"grep -c \"showSupportRequestDialog\" desktop_home_page.dart || \\  echo \"\u26a0\ufe0f Patch did not apply!\"<\/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>\u0421\u0435\u0439\u0447\u0430\u0441 \u0432\u0441\u0435 \u043f\u0430\u0442\u0447\u0438 \u0432\u0430\u043b\u0438\u0434\u0438\u0440\u0443\u044e\u0442\u0441\u044f &#8212; \u0435\u0441\u043b\u0438 grep \u0432\u0435\u0440\u043d\u0443\u043b 0, \u0432 \u043b\u043e\u0433\u0430\u0445 \u0441\u0431\u043e\u0440\u043a\u0438 \u0432\u0438\u0434\u043d\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443, \u0438 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0440\u0435\u0433\u0435\u043a\u0441\u043f.<\/p>\n<h3>\u0417\u0430\u0449\u0438\u0442\u0430 \u043e\u0442 \u043c\u043e\u0448\u0435\u043d\u043d\u0438\u0447\u0435\u0441\u0442\u0432\u0430: \u0443\u0431\u0438\u0440\u0430\u0435\u043c \u043f\u0440\u0438\u0451\u043c \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0441 Android<\/h3>\n<p>\u042d\u0442\u043e \u0442\u0430 \u0444\u0438\u0448\u043a\u0430, \u0440\u0430\u0434\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 Google Play, RuStore \u0438 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u043e\u043b\u044e\u0431\u0438\u0442\u044c \u043d\u0430\u0448\u0443 \u0441\u0431\u043e\u0440\u043a\u0443.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a16\/42f\/904\/a1642f90468b83b2c3f2e15d227f439c.png\" alt=\"\u0427\u0430\u0441\u0442\u044c \u043e\u043a\u043d\u0430 \u0441\u0431\u043e\u0440\u043a\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 Android\" title=\"\u0427\u0430\u0441\u0442\u044c \u043e\u043a\u043d\u0430 \u0441\u0431\u043e\u0440\u043a\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 Android\" width=\"962\" height=\"503\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/a16\/42f\/904\/a1642f90468b83b2c3f2e15d227f439c.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a16\/42f\/904\/a1642f90468b83b2c3f2e15d227f439c.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0427\u0430\u0441\u0442\u044c \u043e\u043a\u043d\u0430 \u0441\u0431\u043e\u0440\u043a\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 Android<\/figcaption><\/div>\n<\/figure>\n<p>\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0440\u043e\u0441\u0441\u0438\u0439\u0441\u043a\u043e\u0433\u043e \u043c\u043e\u0448\u0435\u043d\u043d\u0438\u0447\u0435\u0441\u0442\u0432\u0430:<\/p>\n<ol>\n<li>\n<p>\u0411\u0430\u0431\u0443\u0448\u043a\u0435 \u0437\u0432\u043e\u043d\u044f\u0442 \u00ab\u0438\u0437 \u0431\u0430\u043d\u043a\u0430\u00bb<\/p>\n<\/li>\n<li>\n<p>\u0421\u043a\u0430\u0447\u0430\u0439\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \/ AnyDesk \/ RustDesk<\/p>\n<\/li>\n<li>\n<p>\u0411\u0430\u0431\u0443\u0448\u043a\u0430 \u0434\u0438\u043a\u0442\u0443\u0435\u0442 \u0441\u0432\u043e\u0439 ID<\/p>\n<\/li>\n<li>\n<p>\u041c\u043e\u0448\u0435\u043d\u043d\u0438\u043a \u0437\u0430\u0445\u043e\u0434\u0438\u0442, \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442 \u0434\u0435\u043d\u044c\u0433\u0438 \u0447\u0435\u0440\u0435\u0437 \u0421\u0431\u0435\u0440\u0431\u0430\u043d\u043a \u041e\u043d\u043b\u0430\u0439\u043d<\/p>\n<\/li>\n<\/ol>\n<p><strong>\u042f \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u044b\u0440\u0435\u0437\u0430\u044e \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0440\u0435\u0436\u0438\u043c \u0438\u0437 Android-\u0441\u0431\u043e\u0440\u043a\u0438.<\/strong>\u00a0\u041f\u0440\u0438 \u0441\u0431\u043e\u0440\u043a\u0435 \u0441 \u0444\u043b\u0430\u0433\u043e\u043c\u00a0<code>outgoing_only=true<\/code>:<\/p>\n<pre><code># 1. \u041d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 Rust: is_outgoing_only() \u0432\u0441\u0435\u0433\u0434\u0430 truesed -i -E 's|SyncReturn\\(config::is_outgoing_only\\(\\)\\)|SyncReturn(true)|g' \\  src\/flutter_ffi.rs# 2. \u041d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 Dart: \u043d\u0430\u0441\u0438\u043b\u044c\u043d\u043e \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u043c Server tabsed -i 's|if (isAndroid &amp;&amp; !bind.isOutgoingOnly())|if (false)|' \\  flutter\/lib\/mobile\/pages\/home_page.dart# 3. \u0418\u0437 AndroidManifest \u0443\u0434\u0430\u043b\u044f\u0435\u043c \u043e\u043f\u0430\u0441\u043d\u044b\u0435 permissionssed -i '\/&lt;uses-permission[^&gt;]*FOREGROUND_SERVICE_MEDIA_PROJECTION[^&gt;]*\/d' \"$MANIFEST\"sed -i '\/&lt;uses-permission[^&gt;]*RECORD_AUDIO[^&gt;]*\/d' \"$MANIFEST\"sed -i '\/&lt;uses-permission[^&gt;]*SYSTEM_ALERT_WINDOW[^&gt;]*\/d' \"$MANIFEST\"<\/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>\u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0438\u0440\u0443\u044e\u0449\u0435\u043c APK\u00a0<strong>\u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435\u0442<\/strong>\u00a0\u043d\u0438 UI \u0434\u043b\u044f \u043f\u0440\u0438\u043d\u044f\u0442\u0438\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f, \u043d\u0438 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u043d\u0430 \u0437\u0430\u0445\u0432\u0430\u0442 \u044d\u043a\u0440\u0430\u043d\u0430\/\u0437\u0432\u0443\u043a\u0430\/overlay. \u0421\u043a\u0430\u0447\u0430\u043b, \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043b, \u043e\u0442\u043a\u0440\u044b\u043b &#8212; \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c: \u043d\u0430\u0431\u0440\u0430\u0442\u044c ID \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u043a \u041f\u041a. \u041f\u0440\u0438\u043d\u044f\u0442\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u00a0<strong>\u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e<\/strong>. \u041e\u0442 \u0441\u043b\u043e\u0432\u0430 \u0441\u043e\u0432\u0441\u0435\u043c.<\/p>\n<p>\u042d\u0442\u043e:<\/p>\n<ul>\n<li>\n<p>\u0417\u0430\u0449\u0438\u0449\u0430\u0435\u0442 \u0431\u0430\u0431\u0443\u0448\u0435\u043a \ud83d\ude09<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 Google Play \/ RuStore \u0431\u0435\u0437 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043e\u043a (\u0442\u0435\u043e\u0440\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438 &#8212; Kaspersky \u0432\u0441\u0451 \u0435\u0449\u0451 \u0440\u0443\u0433\u0430\u0435\u0442\u0441\u044f, \u0441\u043c. \u043d\u0438\u0436\u0435)<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u043a \u043f\u043e\u0434\u0430\u0447\u0435 \u0432 \u0420\u0435\u0435\u0441\u0442\u0440 \u0440\u043e\u0441\u0441\u0438\u0439\u0441\u043a\u043e\u0433\u043e \u041f\u041e \u043a\u0430\u043a \u00ab\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f\u00bb<\/p>\n<\/li>\n<\/ul>\n<h4>\u0410 \u0447\u0442\u043e \u0441 Kaspersky?<\/h4>\n<p>\u041a\u043e\u0433\u0434\u0430 \u044f \u043f\u043e\u0434\u0430\u043b APK \u0432 RuStore, \u041a\u0430\u0441\u043f\u0435\u0440\u0441\u043a\u0438\u0439 \u0437\u0430\u0434\u0435\u0442\u0435\u043a\u0442\u0438\u043b \u0435\u0433\u043e \u043a\u0430\u043a\u00a0<code>not-a-virus:HEUR:RemoteAdmin.AndroidOS.RustDesk.a<\/code>. \u041f\u0440\u0435\u0444\u0438\u043a\u0441\u00a0<code>not-a-virus<\/code>\u00a0\u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 PUA (Potentially Unwanted Application) &#8212; \u0442\u043e\u0442 \u0436\u0435 \u043a\u043b\u0430\u0441\u0441 \u0447\u0442\u043e \u0438 AnyDesk\/TeamViewer \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0442.<\/p>\n<p>\u042d\u0432\u0440\u0438\u0441\u0442\u0438\u043a\u0430 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043d\u0430 \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u0443\u00a0<a href=\"http:\/\/librustdesk.so\" rel=\"noopener noreferrer nofollow\"><code>librustdesk.so<\/code><\/a>\u00a0\u0432 APK. \u0420\u0435\u0448\u0435\u043d\u0438\u0435 &#8212; \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0442\u0438\u0432\u043d\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u043d\u0430 \u043b\u0435\u0442\u0443:<\/p>\n<pre><code>NATIVE_NAME=\"evertydesk\"# \u0424\u0430\u0439\u043b .so \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 jniLibs \u043f\u043e\u0434 \u043d\u043e\u0432\u044b\u043c \u0438\u043c\u0435\u043d\u0435\u043ccp .\/target\/release\/liblibrustdesk.so \\   .\/flutter\/android\/app\/src\/main\/jniLibs\/arm64-v8a\/lib${NATIVE_NAME}.so# \u0418 Kotlin \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u043f\u043e \u043d\u043e\u0432\u043e\u043c\u0443 \u0438\u043c\u0435\u043d\u0438sed -i \"s|System.loadLibrary(\\\"rustdesk\\\")|System.loadLibrary(\\\"${NATIVE_NAME}\\\")|\" \\  .\/flutter\/android\/app\/src\/main\/kotlin\/com\/...\/ffi.kt<\/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\u043b\u044e\u0441 \u0430\u043f\u0435\u043b\u043b\u044f\u0446\u0438\u044f \u0432 RuStore \u0441 \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u0435\u043c \u0447\u0442\u043e \u044d\u0442\u043e PUA, \u0447\u0442\u043e \u043d\u0430\u0448 \u043a\u043b\u0438\u0435\u043d\u0442 outgoing-only, \u0438 \u0447\u0442\u043e \u0432\u043e\u043e\u0431\u0449\u0435 \u00abnot-a-virus\u00bb &#8212; \u044d\u0442\u043e \u043d\u0435 \u0432\u0438\u0440\u0443\u0441. \u0414\u043e\u043b\u0436\u043d\u043e \u0440\u0435\u0448\u0438\u0442\u044c. \u0416\u0434\u0435\u043c\u0441.<\/p>\n<h3>Smart Agent &#8212; peer-to-peer \u043f\u043e\u043c\u043e\u0449\u044c \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u0430\u043c\u0438<\/h3>\n<p>\u042d\u0442\u0430 \u0444\u0438\u0447\u0430 &#8212; \u0442\u043e, \u0447\u0435\u0433\u043e \u043d\u0435\u0442 \u043d\u0438 \u0443 TeamViewer, \u043d\u0438 \u0443 AnyDesk, \u043d\u0438 \u0443 \u0441\u0430\u043c\u043e\u0433\u043e RustDesk.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/743\/6a5\/fbf\/7436a5fbf38ef3803de2e12e9a5fa3e6.png\" alt=\"\u041e\u043a\u043d\u043e \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430\" title=\"\u041e\u043a\u043d\u043e \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430\" width=\"1000\" height=\"527\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/743\/6a5\/fbf\/7436a5fbf38ef3803de2e12e9a5fa3e6.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/743\/6a5\/fbf\/7436a5fbf38ef3803de2e12e9a5fa3e6.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041e\u043a\u043d\u043e \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430<\/figcaption><\/div>\n<\/figure>\n<p>\u0412 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442 \u044f \u0438\u043d\u0436\u0435\u043a\u0442\u0438\u0440\u0443\u044e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 Dart-\u0441\u0435\u0440\u0432\u0438\u0441 (<code>agent_service.dart<\/code>), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0444\u043e\u043d\u043e\u043c \u0432\u043d\u0443\u0442\u0440\u0438 RustDesk-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430. \u0414\u0435\u043b\u0430\u0435\u0442 \u0442\u0440\u0438 \u0432\u0435\u0449\u0438:<\/p>\n<ol>\n<li>\n<p><strong>Heartbeat<\/strong>\u00a0\u043d\u0430 \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0435\u0440 \u043a\u0430\u0436\u0434\u0443\u044e \u043c\u0438\u043d\u0443\u0442\u0443 (\u043e\u043d\u043b\u0430\u0439\u043d-\u0441\u0442\u0430\u0442\u0443\u0441 \u043c\u0430\u0448\u0438\u043d\u044b)<\/p>\n<\/li>\n<li>\n<p><strong>Inbox-\u043f\u043e\u043b\u043b<\/strong>\u00a0\u043a\u0430\u0436\u0434\u044b\u0435 30 \u0441\u0435\u043a\u0443\u043d\u0434 (\u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f &#8212; \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 push \u043e\u0442 \u0430\u0434\u043c\u0438\u043d\u0430)<\/p>\n<\/li>\n<li>\n<p><strong>\u0417\u0430\u043f\u0440\u043e\u0441 \u043f\u043e\u043c\u043e\u0449\u0438<\/strong>\u00a0&#8212; \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0436\u043c\u0451\u0442 \u043a\u043d\u043e\u043f\u043a\u0443 \u0432 UI \u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430, \u0442\u043e\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 popup \u0441 \u043a\u043d\u043e\u043f\u043a\u0430\u043c\u0438\u00a0<code>[\u041f\u0440\u0438\u043d\u044f\u0442\u044c] [\u0427\u0435\u0440\u0435\u0437 10 \u043c\u0438\u043d] [\u0427\u0435\u0440\u0435\u0437 \u0447\u0430\u0441] [\u041e\u0442\u043a\u043b\u043e\u043d\u0438\u0442\u044c]<\/code><\/p>\n<\/li>\n<\/ol>\n<p>\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u043e \u044d\u0442\u043e \u043d\u0430\u0434\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043d\u0430\u0434 RustDesk-\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u043e\u043c,\u00a0<strong>\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u0430\u043d\u0430\u043b<\/strong>, \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0439 relay. \u0427\u0435\u0440\u0435\u0437 \u043d\u0430\u0448 HTTP API.<\/p>\n<pre><code>class AgentService {  static const Duration kInboxInterval = Duration(seconds: 30);  static const Duration kHeartbeatInterval = Duration(minutes: 1);  Future&lt;void&gt; _checkInbox() async {    final resp = await http.get(      Uri.parse('$_apiServer\/admin\/agent\/inbox').replace(queryParameters: {        'machine_id': _machineId,        'service_key': _serviceKey,      }),    ).timeout(kHttpTimeout);    if (resp.statusCode != 200) {      _inboxFailures++;      return;    }    _inboxFailures = 0;    final items = jsonDecode(resp.body)['items'] as List;    for (final item in items) {      if (item['type'] == 'support_ping') {        showSupportPingDialog(ctx, item); \/\/ Popup \u0441\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f\u043c\u0438      }      \/\/ ... \u0434\u0440\u0443\u0433\u0435 \u0442\u0438\u043f\u044b: banner, poll, config_update    }  }}<\/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\u0434\u0435\u0441\u044c \u0431\u044b\u043b\u0430 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430\u044f \u0431\u043e\u043b\u044c: \u043f\u0435\u0440\u0432\u044b\u0439 \u0440\u0430\u0437 \u044f \u043f\u0440\u043e\u0441\u0442\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u00a0<code>target_machine_id<\/code>\u00a0\u043a\u0430\u043a \u0441\u0442\u0440\u043e\u043a\u0443 \u0432 \u043f\u043e\u043b\u0435\u00a0<code>target_ids<\/code>\u00a0AgentNotification. \u0410 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 inbox-\u0444\u0438\u043b\u044c\u0442\u0440 \u043f\u0430\u0440\u0441\u0438\u0442 \u044d\u0442\u043e \u043a\u0430\u043a JSON-\u043c\u0430\u0441\u0441\u0438\u0432. Json.Unmarshal \u043f\u0430\u0434\u0430\u043b \u2192\u00a0<code>continue<\/code>\u00a0\u2192 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435\u00a0<strong>\u043c\u043e\u043b\u0447\u0430 \u043d\u0435 \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u043b\u043e\u0441\u044c<\/strong>. \u0421\u0438\u043c\u043f\u0442\u043e\u043c &#8212; \u00ab\u043d\u0430\u0436\u0438\u043c\u0430\u044e \u0417\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u043f\u043e\u043c\u043e\u0449\u044c, \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u00bb. \u0414\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0430 \u0437\u0430\u043d\u044f\u043b\u0430 \u043f\u0430\u0440\u0443 \u0447\u0430\u0441\u043e\u0432:  <\/p>\n<pre><code>\/\/ \u0411\u044b\u043b\u043e:TargetIds: resolvedTarget,  \/\/ \u2190 \"abc123\"\/\/ \u0421\u0442\u0430\u043b\u043e:targetIdsJson, _ := json.Marshal([]string{resolvedTarget})TargetIds: string(targetIdsJson),  \/\/ \u2190 `[\"abc123\"]`<\/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>\u0423\u0440\u043e\u043a: \u0435\u0441\u043b\u0438 \u0432\u0430\u0448 \u043f\u0430\u0440\u0441\u0435\u0440 \u0441\u0442\u0440\u043e\u0433\u0438\u0439, \u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c\u00a0<code>continue-on-error<\/code>, \u043e\u0448\u0438\u0431\u043a\u0438 \u043f\u0440\u044f\u0447\u0443\u0442\u0441\u044f. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0432\u0435\u0437\u0434\u0435, \u0433\u0434\u0435 \u0440\u0430\u043d\u044c\u0448\u0435 \u0431\u044b\u043b\u043e silent-fail, \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e counter (<code>_inboxFailures++<\/code>) \u0438 \u043b\u043e\u0433\u0438\u0440\u0443\u044e.<\/p>\n<p><strong>\u0423\u0440\u043e\u0432\u0435\u043d\u044c 2 &#8212; \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043a \u0442\u0435\u043d\u0430\u043d\u0442\u0443 \u043f\u0440\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438<\/strong>. \u042d\u0442\u043e \u0442\u0430 \u0447\u0430\u0441\u0442\u044c, \u0433\u0434\u0435 RustDesk \u0440\u043e\u0434\u043d\u043e\u0439 \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0437\u043d\u0430\u0435\u0442 \u043f\u0440\u043e \u0442\u0435\u043d\u0430\u043d\u0442\u0430. \u0423 \u043c\u0435\u043d\u044f \u0441\u043c\u0435\u0448\u043d\u043e: heartbeat \u043e\u0442 RustDesk-\u043a\u043b\u0438\u0435\u043d\u0442\u0430 (<code>\/api\/heartbeat<\/code>) \u043d\u0435 \u043d\u0435\u0441\u0451\u0442 \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e tenant-id&#8217;\u0430 &#8212; \u0442\u0430\u043c \u0442\u043e\u043b\u044c\u043a\u043e\u00a0<code>{id, uuid, conns}<\/code>. \u0422\u043e \u0435\u0441\u0442\u044c \u0432\u0441\u0435 10 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0439 \u0448\u043b\u044e\u0442 heartbeat \u0432 \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 default-\u0430\u043a\u043a\u0430\u0443\u043d\u0442.<\/p>\n<p>\u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430\u0448\u043b\u043e\u0441\u044c \u0447\u0435\u0440\u0435\u0437 Smart Agent. \u041e\u043d-\u0442\u043e \u0437\u043d\u0430\u0435\u0442 \u0441\u0432\u043e\u0439\u00a0<code>service_key<\/code>\u00a0(slug \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438, \u0437\u0430\u0448\u0438\u0442\u044b\u0439 \u043f\u0440\u0438 \u0441\u0431\u043e\u0440\u043a\u0435) &#8212; \u043a\u0430\u0436\u0434\u044b\u0435 60 \u0441\u0435\u043a\u0443\u043d\u0434 \u0448\u043b\u0451\u0442 \u0435\u0433\u043e \u043d\u0430\u00a0<code>\/admin\/agent\/heartbeat<\/code>. \u0421\u0435\u0440\u0432\u0435\u0440:<\/p>\n<pre><code>\/\/        \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c \u0430\u0433\u0435\u043d\u0442\u0441\u043a\u043e\u043c heartbeat:if saId &gt; 0 {  \/\/ \u041d\u0430\u0445\u043e\u0434\u0438\u043c Device \u0441 \u0442\u0435\u043c \u0436\u0435 rustdesk_id \u0438 \u043f\u0435\u0440\u0435\u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0435\u043c \u043a \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c\u0443 \u0442\u0435\u043d\u0430\u043d\u0442\u0443  c.Db.Where(\"rustdesk_id = ?\", machineId).    Cols(\"service_account_id\", \"is_pending\").    Update(&amp;model.Device{      ServiceAccountId: saId,      IsPending:        false,    })}<\/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>\u0422\u043e \u0435\u0441\u0442\u044c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0432 &#171;pending pool&#187; (\u043d\u0435 \u0432\u0438\u0434\u043d\u043e \u043d\u0438\u043a\u043e\u043c\u0443), \u0430 \u043f\u043e\u0442\u043e\u043c Smart Agent \u0435\u0433\u043e \u00ab\u0437\u0430\u0431\u0438\u0440\u0430\u0435\u0442\u00bb \u0432 \u043d\u0443\u0436\u043d\u044b\u0439 \u0442\u0435\u043d\u0430\u043d\u0442. \u0427\u0435\u0440\u0435\u0437 30-60 \u0441\u0435\u043a\u0443\u043d\u0434 \u043f\u043e\u0441\u043b\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u043c\u0430\u0448\u0438\u043d\u0430 \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u043a\u0430\u0431\u0438\u043d\u0435\u0442\u0435 \u043d\u0443\u0436\u043d\u043e\u0439 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438.<\/p>\n<p>\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e &#8212; pending-pool \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u0430\u043a \u00ab\u043c\u043e\u0434\u0435\u0440\u0430\u0446\u0438\u044f\u00bb: \u0435\u0441\u043b\u0438 \u043f\u043e \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u0430\u0433\u0435\u043d\u0442 \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b\u0441\u044f, \u0432\u043b\u0430\u0434\u0435\u043b\u0435\u0446 \u0432\u0438\u0434\u0438\u0442 \u0432 \u0430\u0434\u043c\u0438\u043d\u043a\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 \u00ab\u041f\u0440\u0438\u043d\u044f\u0442\u044c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u00bb \u0438 \u043c\u043e\u0436\u0435\u0442 \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u0442\u044c \u043a \u043a\u043b\u0438\u0435\u043d\u0442\u0443. \u042d\u0442\u043e\u00a0<strong>AnyDesk-style enrollment<\/strong>\u00a0\u043d\u0430 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u043a\u0430\u0445.<\/p>\n<h3>\u041a\u043e\u0440\u043f\u043e\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0439 SSO: Active Directory + \u042f\u043d\u0434\u0435\u043a\u0441 ID<\/h3>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/9cf\/b5b\/89a\/9cfb5b89a69d4d62d9d0ef5df7e41037.png\" alt=\"\u0427\u0430\u0441\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0434\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 AD\" title=\"\u0427\u0430\u0441\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0434\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 AD\" width=\"1636\" height=\"728\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/9cf\/b5b\/89a\/9cfb5b89a69d4d62d9d0ef5df7e41037.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/9cf\/b5b\/89a\/9cfb5b89a69d4d62d9d0ef5df7e41037.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0427\u0430\u0441\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0434\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 AD<\/figcaption><\/div>\n<\/figure>\n<p><strong>LDAP\/AD<\/strong>\u00a0\u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0442\u0430\u043a, \u0447\u0442\u043e\u00a0<strong>\u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043f\u0430\u0442\u0447\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0430<\/strong>. \u042e\u0437\u0435\u0440 \u0432 RustDesk \u0436\u043c\u0451\u0442 \u00abSign in\u00bb, \u0432\u0432\u043e\u0434\u0438\u0442 \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u0439 \u043b\u043e\u0433\u0438\u043d\/\u043f\u0430\u0440\u043e\u043b\u044c. \u0421\u0435\u0440\u0432\u0435\u0440 \u0432\u0438\u0434\u0438\u0442 \u0432 \u0435\u0433\u043e tenant&#8217;\u0435 \u0435\u0441\u0442\u044c LDAP &#8212; \u043f\u0440\u043e\u0431\u0443\u0435\u0442 bind. \u0415\u0441\u043b\u0438 \u0443\u0441\u043f\u0435\u0445 -\u0441\u043e\u0437\u0434\u0430\u0451\u0442 User, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u043e\u043a\u0435\u043d. Klein client doesn&#8217;t know it talked to LDAP &#8212; \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u0438\u043d\u044f\u043b.<\/p>\n<pre><code>\/\/ \u0412 service\/ldap.go:func LdapAuthenticate(cfg *model.LdapConfig, username, password string) (*LdapAuthResult, error) {    conn, _ := ldap.DialURL(cfg.ServerUrl)    defer conn.Close()    \/\/ 1 Bind \u043a\u0430\u043a \u0441\u0435\u0440\u0432\u0438\u0441\u043d\u044b\u0439  \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430    conn.Bind(cfg.BindDn, cfg.BindPassword)    \/\/ 2 \u041d\u0430\u0439\u0442\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u043e \u0444\u0438\u043b\u044c\u0442\u0440\u0443    filter := strings.ReplaceAll(cfg.UserFilter, \"{username}\",                                 ldap.EscapeFilter(username))    res, _ := conn.Search(...)    \/\/ 3 Bind \u041a\u0410\u041a \u044d\u0442\u043e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u044d\u0442\u043e \u0438 \u0435\u0441\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u0430\u0440\u043e\u043b\u044f    if err := conn.Bind(res.Entries[0].DN, password); err != nil {        return nil, fmt.Errorf(\"invalid_credentials\")    }    \/\/ 4 \u041e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435 \u0432 \u0440\u0430\u0437\u0440\u0435\u0448\u0451\u043d\u0443\u044e \u0433\u0440\u0443\u043f\u043f\u0443    return &amp;LdapAuthResult{...}, nil}<\/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>\u0418 \u0432 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u043c\u00a0<code>\/api\/login<\/code>:  <\/p>\n<pre><code>if !get {    \/\/ \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e    res, accId, err := LdapTryAllAccounts(db, username, password)    if err == nil &amp;&amp; res != nil {        \/\/ LDAP \u043f\u0440\u0438\u043d\u044f\u043b! \u0421\u043e\u0437\u0434\u0430\u0451\u043c User \u043f\u043e\u0434 \u043d\u0443\u0436\u043d\u044b\u043c \u0442\u0435\u043d\u0430\u043d\u0442\u043e\u043c        user = autoProvisionFromLdap(res, accId)    }}<\/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>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442: \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f-\u043a\u043b\u0438\u0435\u043d\u0442 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 LDAP \u0432 \u043a\u0430\u0431\u0438\u043d\u0435\u0442\u0435, \u0432\u0441\u0435 \u0435\u0451 \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u0438 \u043c\u043e\u0433\u0443\u0442 \u043b\u043e\u0433\u0438\u043d\u0438\u0442\u044c\u0441\u044f \u0432 RustDesk-\u043a\u043b\u0438\u0435\u043d\u0442 \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u0443\u0447\u0451\u0442\u043a\u0430\u043c\u0438 \u0431\u0435\u0437 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438. \u041a\u043e\u0433\u0434\u0430 \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u0430 \u0443\u0432\u043e\u043b\u044c\u043d\u044f\u044e\u0442 (\u043e\u0442\u043a\u043b\u044e\u0447\u0430\u044e\u0442 \u0432 AD), \u0435\u0433\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0432\u0445\u043e\u0434 \u0432 RustDesk\u00a0<strong>\u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0435 \u043f\u0440\u043e\u0439\u0434\u0451\u0442<\/strong>.<\/p>\n<p><strong>\u042f\u043d\u0434\u0435\u043a\u0441 ID<\/strong>\u00a0\u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0447\u0435\u0440\u0435\u0437 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 OAuth 2.0 + Device Authorization Grant (RFC 8628). \u0414\u043b\u044f \u0432\u0435\u0431-\u043a\u0430\u0431\u0438\u043d\u0435\u0442\u0430 &#8212; \u043a\u043d\u043e\u043f\u043a\u0430 \u00ab\u0412\u043e\u0439\u0442\u0438 \u0447\u0435\u0440\u0435\u0437 \u042f\u043d\u0434\u0435\u043a\u0441\u00bb, \u0440\u0435\u0434\u0438\u0440\u0435\u043a\u0442, callback. \u0414\u043b\u044f desktop-\u043a\u043b\u0438\u0435\u043d\u0442\u0430 &#8212; Device Code flow: \u043a\u043b\u0438\u0435\u043d\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 code, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0434\u0438\u0430\u043b\u043e\u0433 \u00ab\u041e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 yandex.com\/device, \u0432\u0432\u0435\u0434\u0438\u0442\u0435 ABCD-EFGH\u00bb, \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u0432\u043e\u0434\u0438\u0442, \u043a\u043b\u0438\u0435\u043d\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0442\u043e\u043a\u0435\u043d. \u042d\u0442\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442 \u0434\u043b\u044f CLI-\u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 (<code>gh auth login<\/code>,\u00a0<code>aws sso login<\/code>).<\/p>\n<h3>\u0411\u0438\u043b\u043b\u0438\u043d\u0433 \u0438 \u043e\u043f\u043b\u0430\u0442\u0430 \u0434\u043b\u044f \u0440\u043e\u0441\u0441\u0438\u0439\u0441\u043a\u0438\u0445 \u044e\u0440\u043b\u0438\u0446<\/h3>\n<p>\u042d\u0442\u043e \u0442\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c, \u0433\u0434\u0435 \u0437\u0430\u043f\u0430\u0434\u043d\u044b\u0435 SaaS-\u0441\u0442\u0430\u0440\u0442\u0430\u043f\u044b \u044d\u043a\u043e\u043d\u043e\u043c\u044f\u0442 \u0432\u0440\u0435\u043c\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f Stripe. \u0412 \u0420\u0424 Stripe \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.<\/p>\n<p>\u0423 \u043c\u0435\u043d\u044f:<\/p>\n<ul>\n<li>\n<p><strong>YooKassa<\/strong>\u00a0\u0434\u043b\u044f \u0444\u0438\u0437\u043b\u0438\u0446 &#8212; \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0432 \u043a\u0430\u0431\u0438\u043d\u0435\u0442 \u0447\u0435\u0440\u0435\u0437 \u0438\u0445 API<\/p>\n<\/li>\n<li>\n<p><strong>\u041e\u043f\u043b\u0430\u0442\u0430 \u043f\u043e \u0441\u0447\u0451\u0442\u0443 \u044e\u0440\u043b\u0438\u0446\u0430\u043c<\/strong>\u00a0&#8212; \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 flow:<\/p>\n<ol>\n<li>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442 \u0432 \u043a\u0430\u0431\u0438\u043d\u0435\u0442\u0435 \u0436\u043c\u0451\u0442 \u00ab\u041e\u043f\u043b\u0430\u0442\u0438\u0442\u044c \u043f\u043e \u0441\u0447\u0451\u0442\u0443\u00bb, \u0432\u0432\u043e\u0434\u0438\u0442 \u0418\u041d\u041d\/\u041a\u041f\u041f\/\u0440\u0435\u043a\u0432\u0438\u0437\u0438\u0442\u044b<\/p>\n<\/li>\n<li>\n<p>\u0421\u0435\u0440\u0432\u0435\u0440 \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u00a0<code>InvoiceRequest<\/code>\u00a0\u0441 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u043c \u043d\u043e\u043c\u0435\u0440\u043e\u043c\u00a0<code>2026-0042<\/code><\/p>\n<\/li>\n<li>\n<p>\u042f \u0432 \u0430\u0434\u043c\u0438\u043d\u043a\u0435 \u0432\u0438\u0436\u0443 \u0437\u0430\u044f\u0432\u043a\u0443, \u0432\u044b\u043f\u0438\u0441\u044b\u0432\u0430\u044e PDF \u0432 \u0431\u0430\u043d\u043a\u0435 (\u0443 \u043c\u0435\u043d\u044f \u0422\u043e\u0447\u043a\u0430), \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u044e \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443<\/p>\n<\/li>\n<li>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 email \u0441\u043e \u0441\u0441\u044b\u043b\u043a\u043e\u0439 \u043d\u0430 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u0435 \u0441\u0447\u0451\u0442\u0430<\/p>\n<\/li>\n<li>\n<p>\u041f\u043b\u0430\u0442\u0438\u0442 \u2192 \u0434\u0435\u043d\u044c\u0433\u0438 \u043f\u0430\u0434\u0430\u044e\u0442 \u043d\u0430 \u0440\u0430\u0441\u0447\u0451\u0442\u043d\u044b\u0439 \u0441\u0447\u0451\u0442<\/p>\n<\/li>\n<li>\n<p>\u042f \u043e\u0442\u043c\u0435\u0447\u0430\u044e \u0432 \u0430\u0434\u043c\u0438\u043d\u043a\u0435 \u00ab\u041e\u043f\u043b\u0430\u0447\u0435\u043d\u00bb \u2192 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u043e\u043c<\/p>\n<\/li>\n<\/ol>\n<\/li>\n<\/ul>\n<p>\u041d\u0435 \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0447\u0442\u043e \u044d\u0442\u043e \u0431\u0438\u0437\u043d\u0435\u0441-\u0438\u043d\u043d\u043e\u0432\u0430\u0446\u0438\u044f, \u043d\u043e\u00a0<strong>\u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u0433\u043e\u0442\u043e\u0432\u043e\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0434\u043b\u044f embedded B2B-\u0431\u0438\u043b\u043b\u0438\u043d\u0433\u0430 \u0432 \u0420\u0424<\/strong>\u00a0\u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0435\u0442. \u0423 \u0432\u0441\u0435\u0445 \u043a\u043e\u0441\u0442\u044b\u043b\u0438.<\/p>\n<h3>\u0421\u0442\u0435\u043a, \u0446\u0438\u0444\u0440\u044b, \u043e\u0431\u0435\u0449\u0430\u043d\u0438\u044f<\/h3>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th data-colwidth=\"362\" width=\"362\">\n<p align=\"left\">\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0422\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td data-colwidth=\"362\" width=\"362\">\n<p align=\"left\">Backend API<\/p>\n<\/td>\n<td>\n<p align=\"left\">Go + Iris MVC<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"362\" width=\"362\">\n<p align=\"left\">\u0411\u0430\u0437\u0430<\/p>\n<\/td>\n<td>\n<p align=\"left\">PostgreSQL 16<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"362\" width=\"362\">\n<p align=\"left\">Frontend (\u043a\u0430\u0431\u0438\u043d\u0435\u0442, landing)<\/p>\n<\/td>\n<td>\n<p align=\"left\">Vue 3 + Naive UI + Vite<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"362\" width=\"362\">\n<p align=\"left\">\u041a\u043b\u0438\u0435\u043d\u0442 (\u0434\u0435\u0441\u043a\u0442\u043e\u043f)<\/p>\n<\/td>\n<td>\n<p align=\"left\">RustDesk official + patches<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"362\" width=\"362\">\n<p align=\"left\">Smart Agent (\u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430)<\/p>\n<\/td>\n<td>\n<p align=\"left\">Flutter\/Dart<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"362\" width=\"362\">\n<p align=\"left\">\u0421\u0431\u043e\u0440\u043a\u0430<\/p>\n<\/td>\n<td>\n<p align=\"left\">GitHub Actions<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"362\" width=\"362\">\n<p align=\"left\">\u0414\u0435\u043f\u043b\u043e\u0439<\/p>\n<\/td>\n<td>\n<p align=\"left\">Docker Compose<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>\u0421\u0431\u043e\u0440\u043a\u0430 \u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430 &#8212; 25-40 \u043c\u0438\u043d\u0443\u0442 (\u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0447\u0430\u0441\u0442\u044c &#8212; Rust \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f). \u041f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0434 \u0432\u0441\u0435 4 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b (Win\/Linux\/macOS\/Android).<\/p>\n<p>\u041a \u043a\u043e\u043d\u0446\u0443 \u043c\u0430\u044f 2026 \u0433\u043e\u0434\u0430 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u044e:<\/p>\n<ul>\n<li>\n<p>\u0421\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u044b\u0439 SaaS-\u0440\u0435\u043b\u0438\u0437<\/p>\n<\/li>\n<li>\n<p>\u0410\u043d\u0434\u0440\u043e\u0438\u0434 \u0432 Google Play + RuStore (RuStore \u0441\u0435\u0439\u0447\u0430\u0441 \u043d\u0430 \u0430\u043f\u0435\u043b\u043b\u044f\u0446\u0438\u0438 \u0438\u0437-\u0437\u0430\u00a0<code>HEUR:RustDesk<\/code>\u00a0\u0434\u0435\u0442\u0435\u043a\u0442\u0430)<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u0440\u0438\u0444\u044b \u0432\u0435\u0441\u044f\u0442 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0435, <\/p>\n<p>\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 RuDesktop, \u044f \u043d\u0435 \u0441\u0442\u0440\u043e\u044e \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044e \u0441 \u0438\u043d\u0432\u0435\u0441\u0442\u043e\u0440\u0430\u043c\u0438, \u0431\u0438\u0437\u043d\u0435\u0441-\u043f\u043b\u0430\u043d\u043e\u043c \u043d\u0430 \u043a\u0440\u0443\u0433\u0438 \u042d\u0439\u043b\u0435\u0440\u0430, \u0438 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0435\u0439 \u0424\u0421\u0422\u042d\u041a \u0432 \u043f\u0435\u0440\u0432\u043e\u043c \u043a\u0432\u0430\u0440\u0442\u0430\u043b\u0435 \u043a\u0430\u043a KPI.<\/p>\n<p>\u042f \u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0435\u0448\u0430\u044e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043c\u0435\u043d\u044f \u0441\u0430\u043c\u0443 \u0433\u043e\u0434\u0430\u043c\u0438 \u0431\u0435\u0441\u0438\u043b\u0430: \u00ab\u0434\u0430\u0439\u0442\u0435 \u043c\u043d\u0435 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u043e\u0441\u0441\u0438\u0439\u0441\u043a\u0438\u0439 remote desktop \u0441 \u0447\u0435\u0441\u0442\u043d\u043e\u0439 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u043e\u043d\u043d\u043e\u0439 \u0447\u0438\u0441\u0442\u043e\u0442\u043e\u0439, \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u0439 \u0434\u043b\u044f \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u0438 \u043e\u043f\u043b\u0430\u0447\u0438\u0432\u0430\u0435\u043c\u044b\u0439 \u043f\u043e \u0440\u043e\u0441\u0441\u0438\u0439\u0441\u043a\u0438\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u00bb. \u041a \u0442\u043e\u043c\u0443 \u0436\u0435, \u043f\u0440\u0438\u0437\u043d\u0430\u044e\u0441\u044c \u044f \u0432\u0441\u0435\u0433\u0434\u0430 \u0436\u0430\u0434\u043d\u043e \u0447\u0438\u0442\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u0440\u043e RustDesk \u043d\u0430 \u0445\u0430\u0431\u0440\u0435, \u0447\u0442\u043e\u0436, \u044f \u043d\u0430\u0431\u0440\u0430\u043b \u0443\u0436\u0435 4 &#171;\u043a\u043b\u0438\u0435\u043d\u0442\u0430 &#8212; \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0430&#187; \u0442\u0430\u043a \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c \u0434\u0430\u043b\u044c\u0448\u0435.<\/p>\n<h3>\u041d\u0443 \u0438 \u0441\u0430\u043c\u043e\u0435 \u0432\u0430\u0436\u043d\u043e\u0435 \u0434\u0443\u043c\u0430, Self-hosted \u0432\u0435\u0440\u0441\u0438\u044f: \u0434\u043b\u044f \u0442\u0435\u0445 \u043a\u043e\u043c\u0443 \u043e\u0431\u043b\u0430\u043a\u043e \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442<\/h3>\n<p>\u041d\u0435 \u043a\u0430\u0436\u0434\u043e\u0439 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0433\u043d\u0430\u0442\u044c \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u0443\u044e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0432 \u0447\u0443\u0436\u043e\u0435 \u043e\u0431\u043b\u0430\u043a\u043e. \u0413\u043e\u0441\u044b, \u0431\u0430\u043d\u043a\u0438, \u043c\u0435\u0434\u0438\u0446\u0438\u043d\u0441\u043a\u0438\u0435 \u0443\u0447\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f, \u0412\u041f\u041a-\u0441\u0435\u0433\u043c\u0435\u043d\u0442, \u043a\u043e\u0440\u043f\u043e\u0440\u0430\u0446\u0438\u0438 \u0441 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0441\u043b\u0443\u0436\u0431\u043e\u0439 \u0418\u0411 &#8212; \u0443 \u043d\u0438\u0445 \u0432 \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0430\u0445 \u0447\u0451\u0440\u043d\u044b\u043c \u043f\u043e \u0431\u0435\u043b\u043e\u043c\u0443:\u00a0<strong>\u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0435\u0440\u0438\u043c\u0435\u0442\u0440\u0430, \u0442\u043e\u0447\u043a\u0430<\/strong>. \u0421 \u044d\u0442\u0438\u043c \u0431\u0435\u0441\u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0441\u043f\u043e\u0440\u0438\u0442\u044c.<\/p>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u0441 SaaS \u044f \u0434\u0435\u043b\u0430\u044e\u00a0<strong>self-hosted \u0432\u0435\u0440\u0441\u0438\u044e<\/strong>\u00a0\u0442\u043e\u0433\u043e \u0436\u0435 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430. \u0422\u0430 \u0436\u0435 \u043a\u043e\u0434\u043e\u0432\u0430\u044f \u0431\u0430\u0437\u0430, \u0442\u043e\u0442 \u0436\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b, \u043d\u043e \u0432\u0441\u0451 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u043d\u0430 \u0435\u0433\u043e \u0436\u0435\u043b\u0435\u0437\u0435 \u0438\u043b\u0438 \u0432 \u0435\u0433\u043e \u0447\u0430\u0441\u0442\u043d\u043e\u043c \u043e\u0431\u043b\u0430\u043a\u0435.<\/p>\n<h4>\u0427\u0442\u043e \u0432\u0445\u043e\u0434\u0438\u0442<\/h4>\n<pre><code># docker-compose.yml \u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u043f\u043e\u0441\u043b\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438services:  everty-desk-api:        # Go backend + Vue cabinet    image: everty-desk\/api:1.0  everty-desk-postgres:   # PostgreSQL    image: postgres:16-alpine  everty-desk-hbbs:       # RustDesk ID server    image: rustdesk\/rustdesk-server:latest  everty-desk-hbbr:       # RustDesk relay    image: rustdesk\/rustdesk-server:latest<\/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>\u041e\u0434\u0438\u043d\u00a0<code>docker compose up -d<\/code>, \u0441\u043a\u0440\u0438\u043f\u0442-\u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0449\u0438\u043a pro \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u044b Let&#8217;s Encrypt (\u0438\u043b\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0441\u0432\u043e\u0438\u0445), \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0411\u0414 &#8212; \u0432\u0441\u0451.\u00a0<strong>\u041d\u0438\u043a\u0430\u043a\u0438\u0445 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0437\u0432\u043e\u043d\u043a\u043e\u0432 \u043d\u0430 \u043d\u0430\u0448\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u044b.<\/strong>\u00a0\u041f\u043e\u043b\u043d\u0430\u044f \u0438\u0437\u043e\u043b\u044f\u0446\u0438\u044f.<\/p>\n<h4>\u041a\u0430\u043a \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f<\/h4>\n<p>\u041b\u0438\u0446\u0435\u043d\u0437\u0438\u044f &#8212; \u0433\u043e\u0434\u043e\u0432\u0430\u044f, \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043e\u0444\u043b\u0430\u0439\u043d \u0447\u0435\u0440\u0435\u0437 \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 JWT-\u043a\u043b\u044e\u0447. \u041d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u00ab\u043e\u043d\u043b\u0430\u0439\u043d-\u0447\u0435\u043a\u0438\u043d\u0430\u00bb, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0440\u0443\u0431\u0438\u0442 \u0441\u0435\u0440\u0432\u0435\u0440 \u0435\u0441\u043b\u0438 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u043b\u0451\u0433. \u0415\u0441\u0442\u044c \u043f\u043e\u043a\u0430 \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f <a href=\"https:\/\/desk.everty.ru\/#\/docs\/rustdesk-edesk-pro\" rel=\"noopener noreferrer nofollow\">\u0442\u0443\u0442<\/a>.<\/p>\n<p>\u041b\u0438\u0446\u0435\u043d\u0437\u0438\u044f \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u0430 \u043a \u0434\u043e\u043c\u0435\u043d\u0430\u043c (whitelisted hostnames \u0432 \u0441\u0430\u043c\u043e\u043c JWT), \u0447\u0442\u043e \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0430 \u0434\u0440\u0443\u0433\u043e\u0439 \u0438\u043d\u0441\u0442\u0430\u043d\u0441. \u041f\u0440\u0438 \u0438\u0441\u0442\u0435\u0447\u0435\u043d\u0438\u0438 &#8212; graceful degradation:\u0437\u0430 \u043c\u0435\u0441\u044f\u0446 \u0434\u043e \u043a\u043e\u043d\u0446\u0430 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f, \u043f\u043e\u0441\u043b\u0435 \u0438\u0441\u0442\u0435\u0447\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u044b\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0442\u0441\u044f, \u043d\u043e\u00a0<strong>\u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043c\u0430\u0448\u0438\u043d\u044b \u0438 \u0430\u0434\u0440\u0435\u0441\u043d\u0430\u044f \u043a\u043d\u0438\u0433\u0430 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044e\u0442\u0441\u044f<\/strong>\u00a0\u0434\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u043f\u0440\u043e\u0434\u043b\u0435\u043d\u0438\u044f. \u0411\u0435\u0437 \u00ab\u0432\u0441\u0451 \u043f\u0440\u043e\u043f\u0430\u043b\u043e\u00bb.  <\/p>\n<p>\u0412 self-hosted \u0432\u0445\u043e\u0434\u0438\u0442 \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e \u0432\u0441\u0451, \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u0441\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438, \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438, \u0442\u043e\u043a\u0435\u043d\u044b \u0432\u0441\u0435 \u043d\u0430 \u0432\u0430\u0441. <\/p>\n<h4>\u0421\u0442\u0430\u0442\u0443\u0441: \u0431\u0435\u0442\u0430, \u0440\u0435\u043b\u0438\u0437 &#8212; \u043a\u043e\u043d\u0435\u0446 \u0438\u044e\u043d\u044f<\/h4>\n<p>\u041f\u0440\u044f\u043c\u043e \u0441\u0435\u0439\u0447\u0430\u0441 self-hosted \u0432\u0435\u0440\u0441\u0438\u044f\u00a0<strong>\u0432 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438<\/strong>\u00a0&#8212; \u0443 \u043c\u0435\u043d\u044f \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0430 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u0430\u044f \u0438\u043d\u0441\u0442\u0430\u043b\u043b\u044f\u0446\u0438\u044f \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435, \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438, \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0438, \u0438\u0437\u043e\u043b\u044f\u0446\u0438\u044e, \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f. \u0421 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0430\u043c\u0438 \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0431\u0435\u0434\u0430, \u0435\u0441\u043b\u0438 \u043a\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u043f\u0438\u0448\u0438\u0442\u0435 \u0441 \u043f\u043e\u043c\u0435\u0442\u043a\u043e\u0439 \u043d\u0430 info@everty.ru. <\/p>\n<p><strong>\u041a \u043a\u043e\u043d\u0446\u0443 \u0438\u044e\u043d\u044f 2026 &#8212; \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u043b\u0438\u0437 1.0<\/strong>\u00a0\u0441:<\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u043b\u043d\u044b\u043c installer-\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u043c (<code>curl install.everty.ru\/selfhost.sh | sh<\/code>)<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0435\u0439 (\u043e\u0442 docker compose \u0434\u043e nginx reverse-proxy \u0438 Let&#8217;s Encrypt)<\/p>\n<\/li>\n<li>\n<p>Lifecycle-\u043c\u0435\u043d\u0435\u0434\u0436\u043c\u0435\u043d\u0442\u043e\u043c \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0439 \u0447\u0435\u0440\u0435\u0437 \u043c\u043e\u044e \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u0438\u0432\u043d\u0443\u044e \u043f\u0430\u043d\u0435\u043b\u044c<\/p>\n<\/li>\n<li>\n<p>SLA \u043d\u0430 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0431\u0430\u0433\u043e\u0432 \u0432 \u043f\u0435\u0440\u0432\u044b\u0439 \u0433\u043e\u0434<\/p>\n<\/li>\n<li>\n<p>\u041a\u0430\u043d\u0430\u043b\u043e\u043c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439:\u00a0<code>stable<\/code>\u00a0\/\u00a0<code>beta<\/code>\u00a0\/\u00a0<code>edge<\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0442\u0435\u043c \u043a\u0442\u043e \u0434\u043e\u0447\u0438\u0442\u0430\u043b \u0434\u043e \u043a\u043e\u043d\u0446\u0430, \u0435\u0441\u043b\u0438 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u043e\u0431\u0441\u0443\u0434\u0438\u0442\u044c \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0434\u0435\u0442\u0430\u043b\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 &#8212; \u0431\u0443\u0434\u0443 \u0440\u0430\u0434 \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445.<\/p>\n<p>info@everty.ru<br \/>desk.everty.ru<\/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\/1038580\/\">https:\/\/habr.com\/ru\/articles\/1038580\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0421\u0442\u0430\u0442\u044c\u044f \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0435\u0441\u044f\u0442\u044c \u043b\u0435\u0442 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043b \u0447\u0443\u0436\u0438\u0435 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u044b, \u0430 \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u0435\u043b\u0430\u0435\u0442 \u0442\u043e, \u0447\u0435\u043c \u0445\u043e\u0447\u0435\u0442 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0430\u043c.\u0411\u0435\u0440\u0435\u043c \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439\u00a0RustDesk\u00a0(AGPLv3), \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u043c \u0444\u043e\u0440\u043a, \u043f\u0430\u0442\u0447\u0438\u043c \u0435\u0433\u043e \u043d\u0430 \u043b\u0435\u0442\u0443 \u0432 GitHub Actions \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430. \u041f\u043e\u0432\u0435\u0440\u0445 &#8212; \u0440\u043e\u0441\u0441\u0438\u0439\u0441\u043a\u0430\u044f \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430: \u0441\u0435\u0440\u0432\u0435\u0440\u044b \u0432 \u0420\u0424, \u043e\u043f\u043b\u0430\u0442\u0430 \u043f\u043e \u0441\u0447\u0451\u0442\u0443 \u044e\u0440.\u043b\u0438\u0446\u0430\u043c, \u043a\u043e\u0440\u043f\u043e\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0439 SSO \u0447\u0435\u0440\u0435\u0437 Active Directory \u0438 \u042f\u043d\u0434\u0435\u043a\u0441 ID, \u0437\u0430\u0449\u0438\u0442\u0430 \u043e\u0442 \u043c\u043e\u0448\u0435\u043d\u043d\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043d\u0430 Android.\u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0410\u0440\u0442\u0443\u0440 \u0412\u0430\u043b\u0438\u0435\u0432. \u042f \u0434\u0435\u043b\u0430\u044e \u043d\u0435 \u00ab\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0438\u043c\u043f\u043e\u0440\u0442\u043e\u0437\u0430\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u0441 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0435\u0439 \u0424\u0421\u0422\u042d\u041a\u00bb \u0440\u0430\u0434\u0438 \u0437\u0430\u043a\u0443\u043f\u043e\u043a. \u041f\u0440\u043e\u0441\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 \u043f\u0440\u043e\u0434\u0443\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u0431\u044b \u0441\u0430\u043c \u0445\u043e\u0442\u0435\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0435\u0441\u044f\u0442\u044c \u043b\u0435\u0442 \u043d\u0430\u0437\u0430\u0434, \u043a\u043e\u0433\u0434\u0430 \u0441\u0438\u0434\u0435\u043b \u043d\u0430 \u0441\u0430\u043f\u043f\u043e\u0440\u0442\u0435 \u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432.\u041f\u043e\u0447\u0435\u043c\u0443 \u044f \u0432\u043e\u043e\u0431\u0449\u0435 \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u044e\u0414\u0435\u0441\u044f\u0442\u044c \u043b\u0435\u0442 \u044f \u0431\u044b\u043b \u044d\u043d\u0438\u043a\u0435\u0439\u0449\u0438\u043a\u043e\u043c, \u043f\u043e\u0442\u043e\u043c \u0441\u0438\u0441\u0430\u0434\u043c\u0438\u043d\u043e\u043c, \u043f\u043e\u0442\u043e\u043c \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043e\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0432 IT-\u0430\u0443\u0442\u0441\u043e\u0440\u0441\u0435. \u041f\u0440\u043e\u0448\u0451\u043b TeamViewer, AnyDesk, LiteManager, AeroAdmin, Ammyy, \u0432\u0441\u0451 \u0447\u0442\u043e \u0432\u044b \u0432\u0438\u0434\u0438\u0442\u0435 \u0432\u00a0\u0441\u043f\u0438\u0441\u043a\u0435. \u0423 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u0432\u043e\u0438 \u0442\u0430\u0440\u0430\u043a\u0430\u043d\u044b:AnyDesk \u0441\u0447\u0438\u0442\u0430\u0435\u0442 \u0432\u0430\u0441 \u043a\u043e\u043c\u043c\u0435\u0440\u0447\u0435\u0441\u043a\u0438\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c, \u0435\u0441\u043b\u0438 \u0432\u044b \u043f\u043e\u043c\u043e\u0433\u043b\u0438 \u043c\u0430\u043c\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u0440\u0438\u043d\u0442\u0435\u0440 \u0434\u0432\u0430\u0436\u0434\u044bLiteManager\u00a0&#8212; \u043f\u044b\u0442\u0430\u043b\u0438\u0441\u044c, \u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0438\u0437 2008 \u0433\u043e\u0434\u0430 \u043f\u043b\u044e\u0441 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u044f \u043f\u043e \u0448\u0442\u0443\u043a\u0430\u043c, \u043d\u0435\u0443\u0434\u043e\u0431\u043d\u043eRuDesktop\u00a0&#8212; \u043f\u0440\u043e \u043d\u0438\u0445 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u043d\u0438\u0436\u0435\u041f\u0440\u043e \u0447\u0435\u0441\u0442\u043d\u043e\u0441\u0442\u044c \u0441 AGPLv3 (\u0438 \u043f\u043e\u0447\u0435\u043c\u0443 \u044f \u043d\u0435 \u00ab\u043a\u0430\u043a RuDesktop\u00bb)\u041a\u043e\u0433\u0434\u0430 \u044f \u043d\u0430\u0447\u0430\u043b, \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u043b \u0440\u043e\u0441\u0441\u0438\u0439\u0441\u043a\u0438\u0445 \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u043e\u0432. \u041e\u0434\u0438\u043d \u0438\u0437 \u0437\u0430\u043c\u0435\u0442\u043d\u044b\u0445 &#8212; RuDesktop. \u0423 \u043d\u0438\u0445 \u043d\u0430 \u0441\u0430\u0439\u0442\u0435 \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0435 \u0431\u0435\u0439\u0434\u0436\u0438 \u00ab\u0420\u0435\u0435\u0441\u0442\u0440 \u0440\u043e\u0441\u041f\u041e\u00bb, \u00ab\u0421\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0424\u0421\u0422\u042d\u041a\u00bb, \u0438 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0435 \u0437\u0430\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e &#171;\u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443&#187;. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c &#8212; \u044d\u0442\u043e \u0444\u043e\u0440\u043a RustDesk \u0431\u0435\u0437 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u043e\u0432, \u0447\u0442\u043e\u00a0\u043f\u0440\u044f\u043c\u043e \u043d\u0430\u0440\u0443\u0448\u0430\u0435\u0442 AGPLv3.AGPL &#8212; \u044d\u0442\u043e \u043d\u0435 \u00ab\u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0438 \u0437\u0430\u0431\u044b\u0442\u044c\u00bb. \u042d\u0442\u043e: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0448\u044c &#8212; \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0439 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f. \u0420\u0430\u0437\u0434\u0430\u0451\u0448\u044c \u043a\u0430\u043a \u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 &#8212; \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0439. \u041b\u044e\u0431\u043e\u0439 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438, \u0435\u0441\u043b\u0438 \u0443\u0437\u043d\u0430\u0435\u0442 \u043f\u0440\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435.\u042f \u043d\u0435 \u0445\u043e\u0447\u0443 \u0442\u0430\u043a. \u042d\u0442\u043e \u043a\u0440\u0430\u0442\u043a\u043e\u0441\u0440\u043e\u0447\u043d\u043e \u0432\u044b\u0433\u043e\u0434\u043d\u043e (\u043d\u0438\u043a\u0442\u043e \u043d\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442 \u043f\u0440\u0438 \u0442\u0435\u043d\u0434\u0435\u0440\u0435), \u043d\u043e \u0434\u043e\u043b\u0433\u043e\u0441\u0440\u043e\u0447\u043d\u043e &#8212; \u0442\u0438\u043a\u0430\u044e\u0449\u0430\u044f \u0431\u043e\u043c\u0431\u0430. \u041a\u043e\u0433\u0434\u0430 RustDesk \u043f\u0440\u043e\u0441\u043d\u0451\u0442\u0441\u044f \u0438 \u043f\u043e\u0434\u0430\u0441\u0442 \u0432 \u0441\u0443\u0434 &#8212; \u0432\u0441\u0435 \u044d\u0442\u0438 \u0431\u0435\u0439\u0434\u0436\u0438 \u0438\u0441\u043f\u0430\u0440\u044f\u0442\u0441\u044f.\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0432\u044b\u0431\u0440\u0430\u043b\u00a0\u043f\u043e\u0434\u0445\u043e\u0434 \u00ab\u043d\u0435 \u0444\u043e\u0440\u043a\u00bb. \u041e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u0435 \u043d\u0438\u0436\u0435.\u0413\u043b\u0430\u0432\u043d\u0430\u044f \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0438\u0434\u0435\u044f: \u043f\u0430\u0442\u0447\u0438\u043c upstream \u043d\u0430 \u043b\u0435\u0442\u0443\u041e\u0431\u044b\u0447\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430 when \u0442\u044b \u0434\u0435\u043b\u0430\u0435\u0448\u044c \u043f\u0440\u043e\u0434\u0443\u043a\u0442 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 open-source:\u0424\u043e\u0440\u043a\u0430\u0435\u0448\u044c \u0440\u0435\u043f\u043e\u041c\u0435\u043d\u044f\u0435\u0448\u044c \u043d\u0443\u0436\u043d\u043e\u0435 \u043f\u0440\u044f\u043c\u043e \u0432 \u043a\u043e\u0434\u0435\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0448\u044c fork \u0432\u0435\u0447\u043d\u043e: \u043a\u0430\u0436\u0434\u043e\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 upstream&#8217;\u0430 \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u043c\u0435\u0440\u0436\u0438\u0448\u044c \u0438 \u0440\u0435\u0448\u0430\u0435\u0448\u044c \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u044b\u042d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043d\u043e \u0447\u0435\u0440\u0435\u0437 \u0433\u043e\u0434 upstream \u0443\u0439\u0434\u0451\u0442 \u0434\u0430\u043b\u0435\u043a\u043e, \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0444\u043e\u0440\u043a \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0431\u043e\u043b\u044c\u043d\u043e. \u0423 RustDesk \u043a\u043e\u043c\u043c\u0438\u0442\u044b \u043f\u0440\u0438\u043b\u0435\u0442\u0430\u044e\u0442 \u043a\u0430\u0436\u0434\u044b\u0439 \u0434\u0435\u043d\u044c.\u042f \u0434\u0435\u043b\u0430\u044e \u0438\u043d\u0430\u0447\u0435.\u00a0\u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0441 workflow-\u0441\u0431\u043e\u0440\u043a\u0430\u043c\u0438 \u043f\u0440\u043e\u0441\u0442\u043e\u00a0\u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u0442 upstream \u0438 \u043f\u0430\u0442\u0447\u0438\u0442 sed-\u043e\u043c\u00a0\u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u0441\u0431\u043e\u0440\u043a\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430:- name: Checkout RustDesk source (master)  uses: actions\/checkout@v4  with:    repository: rustdesk\/rustdesk    ref: master    submodules: recursive- name: Aggressive rebrand  if: ${{ inputs.rebrand_strings == &#8216;true&#8217; }}  run: |    find .\/flutter\/lib -name &#171;*.dart&#187; -type f \\      -exec sed -i &#171;s|RustDesk|${APP_NAME}|g&#187; {} +    sed -i &#171;s|hbb_common::config::APP_NAME.read().unwrap().clone()|\\&#187;${APP_NAME}\\&#187;.to_string()|g&#187; \\      .\/src\/common.rs    sed -i &#171;s|android:scheme=\\&#187;rustdesk\\&#187;|android:scheme=\\&#187;${BRAND_LOWER}\\&#187;|g&#187; \\      .\/flutter\/android\/app\/src\/main\/AndroidManifest.xml\u041a\u0430\u0436\u0434\u0430\u044f \u0441\u0431\u043e\u0440\u043a\u0430 \u0442\u044f\u043d\u0435\u0442 \u0441\u0432\u0435\u0436\u0438\u0439 upstream (\u0438\u043b\u0438 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u0442\u0435\u0433, \u043a\u0430\u043a\u043e\u0439 \u043a\u043b\u0438\u0435\u043d\u0442 \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u043b), \u043d\u0430\u043a\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043c\u043e\u0438 \u043f\u0430\u0442\u0447\u0438, \u0431\u0438\u043b\u0434\u0438\u0442, \u0443\u0434\u0430\u043b\u044f\u0435\u0442. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 &#8212;\u00a0.exe,\u00a0.apk,\u00a0.dmg,\u00a0.deb\u00a0\u043f\u043e\u0434 \u043a\u043b\u0438\u0435\u043d\u0442\u0430.\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u0427\u0442\u043e \u044d\u0442\u043e \u0434\u0430\u0451\u0442\u042f \u043d\u0435 \u043e\u0431\u044f\u0437\u0430\u043d \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u0444\u043e\u0440\u043a\u00a0&#8212; \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0444\u043e\u0440\u043a\u0430 \u043d\u0435\u0442. \u0415\u0441\u0442\u044c downstream-\u043f\u0430\u0442\u0447\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0435 (\u0432 \u043c\u043e\u0451\u043c workflow-\u0440\u0435\u043f\u043e) \u0438 AGPL-\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0435.Upstream \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f\u00a0&#8212; \u0437\u0430\u0445\u043e\u0442\u0435\u043b \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0441 RustDesk 1.4.5? \u0423\u043a\u0430\u0437\u0430\u043b\u00a0version: 1.4.5\u00a0&#8212; workflow \u0441\u0430\u043c \u043f\u043e\u0434\u0442\u044f\u043d\u0435\u0442.\u041a\u0430\u0436\u0434\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0410 &#8212; \u044d\u0442\u043e \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u0430\u044f \u0441\u0431\u043e\u0440\u043a\u0430\u00a0\u0441\u043e \u0441\u0432\u043e\u0438\u043c \u0431\u0440\u0435\u043d\u0434\u043e\u043c, \u0441\u0432\u043e\u0438\u043c \u0437\u0430\u0448\u0438\u0442\u044b\u043c tenant slug, \u0441\u0432\u043e\u0438\u043c \u043d\u0430\u0431\u043e\u0440\u043e\u043c \u0444\u0438\u0447\u0435\u0439.\u041a\u0430\u043a\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b\u0413\u043b\u0430\u0432\u043d\u0430\u044f &#8212;\u00a0upstream \u043b\u043e\u043c\u0430\u0435\u0442 \u0438\u043c\u0435\u043d\u0430. \u042f \u043e\u0434\u043d\u0430\u0436\u0434\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043b sed-\u043f\u0430\u0442\u0447 \u043f\u043e\u0434 \u0430\u043d\u043a\u0435\u0440\u00a0PopupMenuButton&lt;String&gt;, \u0430 upstream \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043b \u0432\u0438\u0434\u0436\u0435\u0442 \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u0440\u0435\u043b\u0438\u0437\u0435. Sed \u043c\u043e\u043b\u0447\u0430 \u043d\u0435 \u043d\u0430\u0448\u0451\u043b \u043f\u0430\u0442\u0442\u0435\u0440\u043d (continue-on-error: true), \u0441\u0431\u043e\u0440\u043a\u0430 \u043f\u0440\u043e\u0448\u043b\u0430, \u043d\u043e\u00a0\u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043d\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0441\u044f. \u041e\u0442\u043a\u0440\u044b\u043b \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442 &#8212; \u043d\u0435\u0442 \u043a\u043d\u043e\u043f\u043a\u0438 \u00ab\u0417\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u043f\u043e\u043c\u043e\u0449\u044c\u00bb. \u0414\u043e\u043b\u0433\u043e \u0438\u0441\u043a\u0430\u043b \u043f\u043e\u0447\u0435\u043c\u0443.\u0420\u0435\u0448\u0435\u043d\u0438\u0435: \u043f\u0438\u0441\u0430\u0442\u044c\u00a0defensive multi-anchor patches\u00a0\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0447\u0442\u043e \u043f\u0430\u0442\u0447 \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043b\u0441\u044f:sed -i &#171;s|buildTip(context),|buildTip(context),\\n  Padding(&#8230;)|&#187; desktop_home_page.dartecho &#171;Verification:&#187;grep -c &#171;showSupportRequestDialog&#187; desktop_home_page.dart || \\  echo &#171;\u26a0\ufe0f Patch did not apply!&#187;\u0421\u0435\u0439\u0447\u0430\u0441 \u0432\u0441\u0435 \u043f\u0430\u0442\u0447\u0438 \u0432\u0430\u043b\u0438\u0434\u0438\u0440\u0443\u044e\u0442\u0441\u044f &#8212; \u0435\u0441\u043b\u0438 grep \u0432\u0435\u0440\u043d\u0443\u043b 0, \u0432 \u043b\u043e\u0433\u0430\u0445 \u0441\u0431\u043e\u0440\u043a\u0438 \u0432\u0438\u0434\u043d\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443, \u0438 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0440\u0435\u0433\u0435\u043a\u0441\u043f.\u0417\u0430\u0449\u0438\u0442\u0430 \u043e\u0442 \u043c\u043e\u0448\u0435\u043d\u043d\u0438\u0447\u0435\u0441\u0442\u0432\u0430: \u0443\u0431\u0438\u0440\u0430\u0435\u043c \u043f\u0440\u0438\u0451\u043c \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0441 Android\u042d\u0442\u043e \u0442\u0430 \u0444\u0438\u0448\u043a\u0430, \u0440\u0430\u0434\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 Google Play, RuStore \u0438 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u043e\u043b\u044e\u0431\u0438\u0442\u044c \u043d\u0430\u0448\u0443 \u0441\u0431\u043e\u0440\u043a\u0443.\u0427\u0430\u0441\u0442\u044c \u043e\u043a\u043d\u0430 \u0441\u0431\u043e\u0440\u043a\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 Android\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0440\u043e\u0441\u0441\u0438\u0439\u0441\u043a\u043e\u0433\u043e \u043c\u043e\u0448\u0435\u043d\u043d\u0438\u0447\u0435\u0441\u0442\u0432\u0430:\u0411\u0430\u0431\u0443\u0448\u043a\u0435 \u0437\u0432\u043e\u043d\u044f\u0442 \u00ab\u0438\u0437 \u0431\u0430\u043d\u043a\u0430\u00bb\u0421\u043a\u0430\u0447\u0430\u0439\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \/ AnyDesk \/ RustDesk\u0411\u0430\u0431\u0443\u0448\u043a\u0430 \u0434\u0438\u043a\u0442\u0443\u0435\u0442 \u0441\u0432\u043e\u0439 ID\u041c\u043e\u0448\u0435\u043d\u043d\u0438\u043a \u0437\u0430\u0445\u043e\u0434\u0438\u0442, \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442 \u0434\u0435\u043d\u044c\u0433\u0438 \u0447\u0435\u0440\u0435\u0437 \u0421\u0431\u0435\u0440\u0431\u0430\u043d\u043a \u041e\u043d\u043b\u0430\u0439\u043d\u042f \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u044b\u0440\u0435\u0437\u0430\u044e \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0440\u0435\u0436\u0438\u043c \u0438\u0437 Android-\u0441\u0431\u043e\u0440\u043a\u0438.\u00a0\u041f\u0440\u0438 \u0441\u0431\u043e\u0440\u043a\u0435 \u0441 \u0444\u043b\u0430\u0433\u043e\u043c\u00a0outgoing_only=true:# 1. \u041d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 Rust: is_outgoing_only() \u0432\u0441\u0435\u0433\u0434\u0430 truesed -i -E &#8216;s|SyncReturn\\(config::is_outgoing_only\\(\\)\\)|SyncReturn(true)|g&#8217; \\  src\/flutter_ffi.rs# 2. \u041d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 Dart: \u043d\u0430\u0441\u0438\u043b\u044c\u043d\u043e \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u043c Server tabsed -i &#8216;s|if (isAndroid &amp;&amp; !bind.isOutgoingOnly())|if (false)|&#8217; \\  flutter\/lib\/mobile\/pages\/home_page.dart# 3. \u0418\u0437 AndroidManifest \u0443\u0434\u0430\u043b\u044f\u0435\u043c \u043e\u043f\u0430\u0441\u043d\u044b\u0435 permissionssed -i &#8216;\/&lt;uses-permission[^&gt;]*FOREGROUND_SERVICE_MEDIA_PROJECTION[^&gt;]*\/d&#8217; &#171;$MANIFEST&#187;sed -i &#8216;\/&lt;uses-permission[^&gt;]*RECORD_AUDIO[^&gt;]*\/d&#8217; &#171;$MANIFEST&#187;sed -i &#8216;\/&lt;uses-permission[^&gt;]*SYSTEM_ALERT_WINDOW[^&gt;]*\/d&#8217; &#171;$MANIFEST&#187;\u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0438\u0440\u0443\u044e\u0449\u0435\u043c APK\u00a0\u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435\u0442\u00a0\u043d\u0438 UI \u0434\u043b\u044f \u043f\u0440\u0438\u043d\u044f\u0442\u0438\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f, \u043d\u0438 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u043d\u0430 \u0437\u0430\u0445\u0432\u0430\u0442 \u044d\u043a\u0440\u0430\u043d\u0430\/\u0437\u0432\u0443\u043a\u0430\/overlay. \u0421\u043a\u0430\u0447\u0430\u043b, \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043b, \u043e\u0442\u043a\u0440\u044b\u043b &#8212; \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c: \u043d\u0430\u0431\u0440\u0430\u0442\u044c ID \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u043a \u041f\u041a. \u041f\u0440\u0438\u043d\u044f\u0442\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u00a0\u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e. \u041e\u0442 \u0441\u043b\u043e\u0432\u0430 \u0441\u043e\u0432\u0441\u0435\u043c.\u042d\u0442\u043e:\u0417\u0430\u0449\u0438\u0449\u0430\u0435\u0442 \u0431\u0430\u0431\u0443\u0448\u0435\u043a ;)\u041f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 Google Play \/ RuStore \u0431\u0435\u0437 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043e\u043a (\u0442\u0435\u043e\u0440\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438 &#8212; Kaspersky \u0432\u0441\u0451 \u0435\u0449\u0451 \u0440\u0443\u0433\u0430\u0435\u0442\u0441\u044f, \u0441\u043c. \u043d\u0438\u0436\u0435)\u041f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u043a \u043f\u043e\u0434\u0430\u0447\u0435 \u0432 \u0420\u0435\u0435\u0441\u0442\u0440 \u0440\u043e\u0441\u0441\u0438\u0439\u0441\u043a\u043e\u0433\u043e \u041f\u041e \u043a\u0430\u043a \u00ab\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f\u00bb\u0410 \u0447\u0442\u043e \u0441 Kaspersky?\u041a\u043e\u0433\u0434\u0430 \u044f \u043f\u043e\u0434\u0430\u043b APK \u0432 RuStore, \u041a\u0430\u0441\u043f\u0435\u0440\u0441\u043a\u0438\u0439 \u0437\u0430\u0434\u0435\u0442\u0435\u043a\u0442\u0438\u043b \u0435\u0433\u043e \u043a\u0430\u043a\u00a0not-a-virus:HEUR:RemoteAdmin.AndroidOS.RustDesk.a. \u041f\u0440\u0435\u0444\u0438\u043a\u0441\u00a0not-a-virus\u00a0\u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 PUA (Potentially Unwanted Application) &#8212; \u0442\u043e\u0442 \u0436\u0435 \u043a\u043b\u0430\u0441\u0441 \u0447\u0442\u043e \u0438 AnyDesk\/TeamViewer \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0442.\u042d\u0432\u0440\u0438\u0441\u0442\u0438\u043a\u0430 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043d\u0430 \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u0443\u00a0librustdesk.so\u00a0\u0432 APK. \u0420\u0435\u0448\u0435\u043d\u0438\u0435 &#8212; \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0442\u0438\u0432\u043d\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u043d\u0430 \u043b\u0435\u0442\u0443:NATIVE_NAME=&#187;evertydesk&#187;# \u0424\u0430\u0439\u043b .so \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 jniLibs \u043f\u043e\u0434 \u043d\u043e\u0432\u044b\u043c \u0438\u043c\u0435\u043d\u0435\u043ccp .\/target\/release\/liblibrustdesk.so \\   .\/flutter\/android\/app\/src\/main\/jniLibs\/arm64-v8a\/lib${NATIVE_NAME}.so# \u0418 Kotlin \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u043f\u043e \u043d\u043e\u0432\u043e\u043c\u0443 \u0438\u043c\u0435\u043d\u0438sed -i &#171;s|System.loadLibrary(\\&#187;rustdesk\\&#187;)|System.loadLibrary(\\&#187;${NATIVE_NAME}\\&#187;)|&#187; \\  .\/flutter\/android\/app\/src\/main\/kotlin\/com\/&#8230;\/ffi.kt\u041f\u043b\u044e\u0441 \u0430\u043f\u0435\u043b\u043b\u044f\u0446\u0438\u044f \u0432 RuStore \u0441 \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u0435\u043c \u0447\u0442\u043e \u044d\u0442\u043e PUA, \u0447\u0442\u043e \u043d\u0430\u0448 \u043a\u043b\u0438\u0435\u043d\u0442 outgoing-only, \u0438 \u0447\u0442\u043e \u0432\u043e\u043e\u0431\u0449\u0435 \u00abnot-a-virus\u00bb &#8212; \u044d\u0442\u043e \u043d\u0435 \u0432\u0438\u0440\u0443\u0441. \u0414\u043e\u043b\u0436\u043d\u043e \u0440\u0435\u0448\u0438\u0442\u044c. \u0416\u0434\u0435\u043c\u0441.Smart Agent &#8212; peer-to-peer \u043f\u043e\u043c\u043e\u0449\u044c \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u0430\u043c\u0438\u042d\u0442\u0430 \u0444\u0438\u0447\u0430 &#8212; \u0442\u043e, \u0447\u0435\u0433\u043e \u043d\u0435\u0442 \u043d\u0438 \u0443 TeamViewer, \u043d\u0438 \u0443 AnyDesk, \u043d\u0438 \u0443 \u0441\u0430\u043c\u043e\u0433\u043e RustDesk.\u041e\u043a\u043d\u043e \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u0412 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442 \u044f \u0438\u043d\u0436\u0435\u043a\u0442\u0438\u0440\u0443\u044e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 Dart-\u0441\u0435\u0440\u0432\u0438\u0441 (agent_service.dart), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0444\u043e\u043d\u043e\u043c \u0432\u043d\u0443\u0442\u0440\u0438 RustDesk-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430. \u0414\u0435\u043b\u0430\u0435\u0442 \u0442\u0440\u0438 \u0432\u0435\u0449\u0438:Heartbeat\u00a0\u043d\u0430 \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0435\u0440 \u043a\u0430\u0436\u0434\u0443\u044e \u043c\u0438\u043d\u0443\u0442\u0443 (\u043e\u043d\u043b\u0430\u0439\u043d-\u0441\u0442\u0430\u0442\u0443\u0441 \u043c\u0430\u0448\u0438\u043d\u044b)Inbox-\u043f\u043e\u043b\u043b\u00a0\u043a\u0430\u0436\u0434\u044b\u0435 30 \u0441\u0435\u043a\u0443\u043d\u0434 (\u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f &#8212; \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 push \u043e\u0442 \u0430\u0434\u043c\u0438\u043d\u0430)\u0417\u0430\u043f\u0440\u043e\u0441 \u043f\u043e\u043c\u043e\u0449\u0438\u00a0&#8212; \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0436\u043c\u0451\u0442 \u043a\u043d\u043e\u043f\u043a\u0443 \u0432 UI \u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430, \u0442\u043e\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 popup \u0441 \u043a\u043d\u043e\u043f\u043a\u0430\u043c\u0438\u00a0[\u041f\u0440\u0438\u043d\u044f\u0442\u044c] [\u0427\u0435\u0440\u0435\u0437 10 \u043c\u0438\u043d] [\u0427\u0435\u0440\u0435\u0437 \u0447\u0430\u0441] [\u041e\u0442\u043a\u043b\u043e\u043d\u0438\u0442\u044c]\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u043e \u044d\u0442\u043e \u043d\u0430\u0434\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043d\u0430\u0434 RustDesk-\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u043e\u043c,\u00a0\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u0430\u043d\u0430\u043b, \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0439 relay. \u0427\u0435\u0440\u0435\u0437 \u043d\u0430\u0448 HTTP API.class AgentService {  static const Duration kInboxInterval = Duration(seconds: 30);  static const Duration kHeartbeatInterval = Duration(minutes: 1);  Future&lt;void&gt; _checkInbox() async {    final resp = await http.get(      Uri.parse(&#8216;$_apiServer\/admin\/agent\/inbox&#8217;).replace(queryParameters: {        &#8216;machine_id&#8217;: _machineId,        &#8216;service_key&#8217;: _serviceKey,      }),    ).timeout(kHttpTimeout);    if (resp.statusCode != 200) {      _inboxFailures++;      return;    }    _inboxFailures = 0;    final items = jsonDecode(resp.body)[&#8216;items&#8217;] as List;    for (final item in items) {      if (item[&#8216;type&#8217;] == &#8216;support_ping&#8217;) {        showSupportPingDialog(ctx, item); \/\/ Popup \u0441\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f\u043c\u0438      }      \/\/ &#8230; \u0434\u0440\u0443\u0433\u0435 \u0442\u0438\u043f\u044b: banner, poll, config_update    }  }}\u0417\u0434\u0435\u0441\u044c \u0431\u044b\u043b\u0430 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430\u044f \u0431\u043e\u043b\u044c: \u043f\u0435\u0440\u0432\u044b\u0439 \u0440\u0430\u0437 \u044f \u043f\u0440\u043e\u0441\u0442\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u00a0target_machine_id\u00a0\u043a\u0430\u043a \u0441\u0442\u0440\u043e\u043a\u0443 \u0432 \u043f\u043e\u043b\u0435\u00a0target_ids\u00a0AgentNotification. \u0410 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 inbox-\u0444\u0438\u043b\u044c\u0442\u0440 \u043f\u0430\u0440\u0441\u0438\u0442 \u044d\u0442\u043e \u043a\u0430\u043a JSON-\u043c\u0430\u0441\u0441\u0438\u0432. Json.Unmarshal \u043f\u0430\u0434\u0430\u043b \u2192\u00a0continue\u00a0\u2192 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435\u00a0\u043c\u043e\u043b\u0447\u0430 \u043d\u0435 \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u043b\u043e\u0441\u044c. \u0421\u0438\u043c\u043f\u0442\u043e\u043c &#8212; \u00ab\u043d\u0430\u0436\u0438\u043c\u0430\u044e \u0417\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u043f\u043e\u043c\u043e\u0449\u044c, \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u00bb. \u0414\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0430 \u0437\u0430\u043d\u044f\u043b\u0430 \u043f\u0430\u0440\u0443 \u0447\u0430\u0441\u043e\u0432:  \/\/ \u0411\u044b\u043b\u043e:TargetIds: resolvedTarget,  \/\/ \u2190 &#171;abc123&#8243;\/\/ \u0421\u0442\u0430\u043b\u043e:targetIdsJson, _ := json.Marshal([]string{resolvedTarget})TargetIds: string(targetIdsJson),  \/\/ \u2190 `[&#171;abc123&#187;]`\u0423\u0440\u043e\u043a: \u0435\u0441\u043b\u0438 \u0432\u0430\u0448 \u043f\u0430\u0440\u0441\u0435\u0440 \u0441\u0442\u0440\u043e\u0433\u0438\u0439, \u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c\u00a0continue-on-error, \u043e\u0448\u0438\u0431\u043a\u0438 \u043f\u0440\u044f\u0447\u0443\u0442\u0441\u044f. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0432\u0435\u0437\u0434\u0435, \u0433\u0434\u0435 \u0440\u0430\u043d\u044c\u0448\u0435 \u0431\u044b\u043b\u043e silent-fail, \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e counter (_inboxFailures++) \u0438 \u043b\u043e\u0433\u0438\u0440\u0443\u044e.\u0423\u0440\u043e\u0432\u0435\u043d\u044c 2 &#8212; \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043a \u0442\u0435\u043d\u0430\u043d\u0442\u0443 \u043f\u0440\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438. \u042d\u0442\u043e \u0442\u0430 \u0447\u0430\u0441\u0442\u044c, \u0433\u0434\u0435 RustDesk \u0440\u043e\u0434\u043d\u043e\u0439 \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0437\u043d\u0430\u0435\u0442 \u043f\u0440\u043e \u0442\u0435\u043d\u0430\u043d\u0442\u0430. \u0423 \u043c\u0435\u043d\u044f \u0441\u043c\u0435\u0448\u043d\u043e: heartbeat \u043e\u0442 RustDesk-\u043a\u043b\u0438\u0435\u043d\u0442\u0430 (\/api\/heartbeat) \u043d\u0435 \u043d\u0435\u0441\u0451\u0442 \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e tenant-id&#8217;\u0430 &#8212; \u0442\u0430\u043c \u0442\u043e\u043b\u044c\u043a\u043e\u00a0{id, uuid, conns}. \u0422\u043e \u0435\u0441\u0442\u044c \u0432\u0441\u0435 10 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0439 \u0448\u043b\u044e\u0442 heartbeat \u0432 \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 default-\u0430\u043a\u043a\u0430\u0443\u043d\u0442.\u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430\u0448\u043b\u043e\u0441\u044c \u0447\u0435\u0440\u0435\u0437 Smart Agent. \u041e\u043d-\u0442\u043e \u0437\u043d\u0430\u0435\u0442 \u0441\u0432\u043e\u0439\u00a0service_key\u00a0(slug \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438, \u0437\u0430\u0448\u0438\u0442\u044b\u0439 \u043f\u0440\u0438 \u0441\u0431\u043e\u0440\u043a\u0435) &#8212; \u043a\u0430\u0436\u0434\u044b\u0435 60 \u0441\u0435\u043a\u0443\u043d\u0434 \u0448\u043b\u0451\u0442 \u0435\u0433\u043e \u043d\u0430\u00a0\/admin\/agent\/heartbeat. \u0421\u0435\u0440\u0432\u0435\u0440:\/\/        \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c \u0430\u0433\u0435\u043d\u0442\u0441\u043a\u043e\u043c heartbeat:if saId &gt; 0 {  \/\/ \u041d\u0430\u0445\u043e\u0434\u0438\u043c Device \u0441 \u0442\u0435\u043c \u0436\u0435 rustdesk_id \u0438 \u043f\u0435\u0440\u0435\u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0435\u043c \u043a \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c\u0443 \u0442\u0435\u043d\u0430\u043d\u0442\u0443  c.Db.Where(&#171;rustdesk_id = ?&#187;, machineId).    Cols(&#171;service_account_id&#187;, &#171;is_pending&#187;).    Update(&amp;model.Device{      ServiceAccountId: saId,      IsPending:        false,    })}\u0422\u043e \u0435\u0441\u0442\u044c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0432 &#171;pending pool&#187; (\u043d\u0435 \u0432\u0438\u0434\u043d\u043e \u043d\u0438\u043a\u043e\u043c\u0443), \u0430 \u043f\u043e\u0442\u043e\u043c Smart Agent \u0435\u0433\u043e \u00ab\u0437\u0430\u0431\u0438\u0440\u0430\u0435\u0442\u00bb \u0432 \u043d\u0443\u0436\u043d\u044b\u0439 \u0442\u0435\u043d\u0430\u043d\u0442. \u0427\u0435\u0440\u0435\u0437 30-60 \u0441\u0435\u043a\u0443\u043d\u0434 \u043f\u043e\u0441\u043b\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u043c\u0430\u0448\u0438\u043d\u0430 \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u043a\u0430\u0431\u0438\u043d\u0435\u0442\u0435 \u043d\u0443\u0436\u043d\u043e\u0439 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438.\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e &#8212; pending-pool \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u0430\u043a \u00ab\u043c\u043e\u0434\u0435\u0440\u0430\u0446\u0438\u044f\u00bb: \u0435\u0441\u043b\u0438 \u043f\u043e \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u0430\u0433\u0435\u043d\u0442 \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b\u0441\u044f, \u0432\u043b\u0430\u0434\u0435\u043b\u0435\u0446 \u0432\u0438\u0434\u0438\u0442 \u0432 \u0430\u0434\u043c\u0438\u043d\u043a\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 \u00ab\u041f\u0440\u0438\u043d\u044f\u0442\u044c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u00bb \u0438 \u043c\u043e\u0436\u0435\u0442 \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u0442\u044c \u043a \u043a\u043b\u0438\u0435\u043d\u0442\u0443. \u042d\u0442\u043e\u00a0AnyDesk-style enrollment\u00a0\u043d\u0430&#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-480781","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/480781","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=480781"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/480781\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=480781"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=480781"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=480781"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}